您的位置:首页 > 其它

STM32F103mini教程学习总结与心得(二)---->串口通信

2017-11-13 20:48 447 查看
STM32F103mini教程学习总结与心得(二)---->串口通信http://blog.csdn.net/qq_19598969/article/details/75934861

一、串口原理

1.处理器与外部设备通信的两种方式:并行通信(速度快,占用资源多)+串行通信(反之)

2.串行通信(按照数据传送方向分类):

(1)单工:数据传输只支持数据在一个方向上传输

   (2)半双工:允许数据在两个方向上传输,但在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信

   (3)全双工:允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立 的接收和发送能力。 

串行通信三种传送方式

3.串行通信的通信方式

(1)同步通信:带时钟同步信号传输--->SPI,IIC通信 【时钟线+数据线】

(2)异步通信:不带时钟通信信号------>UART(通用异步收发器),单总线 【约定波特率】

常见的串行通信接口

4.STM32的串口通信接口

(1)UART:通用异步收发器

(2)USART:通用同步异步收发器

UART异步通信方式引脚连接方法

STM32F10X的串口对应针脚

5.UART异步通信方式特点:

全双工异步通信。
分数波特率发生器系统,提供精确的波特率(波特率决定数据传输速度)。
-发送和接受共用的可编程波特率,最高可达4.5Mbits/s
可编程的数据字长度(8位或者9位);
可配置的停止位(支持1或者2位停止位);
可配置的使用DMA多缓冲器通信。
单独的发送器和接收器使能位。
检测标志:① 接受缓冲器 ②发送缓冲器空 ③传输结束标志
多个带标志的中断源。触发中断。
其他:校验控制,四个错误检测标志。

串口通信过程

6.串口异步通信需要定义的参数:

起始位
数据位(8位或者9位)
奇偶校验位(第9位)--->偶校验:如果数据位8位中,1的个数为偶数,则校验位为0,反之为1;奇校验相反
停止位(1,15,2位)
波特率设置---->点击打开链接

通信位
7.常用的串口相关寄存器

(1)USART_SR状态寄存器

(2)USART_DR数据寄存器

(3)USART_BRR波特率寄存器 

8.串口操作函数(省略入口参数)
void USART_Init(); //串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能
void USART_Cmd();//使能串口
void USART_ITConfig();//使能相关中断
DR寄存器操作:
void USART_SendData();//发送数据到串口,DR

uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据
SR寄存器操作:
FlagStatus USART_GetFlagStatus();//获取状态标志位

void USART_ClearFlag();//清除状态标志位

ITStatus USART_GetITStatus();//获取中断状态标志位

void USART_ClearITPendingBit();//清除中断状态标志位

二、实际串口寄存器操作

1.miniSTM32板载2个串口:

(1)USB串口(CH340:USB转串口芯片):与电脑通信

(2)RS232串口:异步传输标准接口---STM32内带的USB接口

(3)术语区分:1)串口、COM口是指的物理接口形式(硬件)【COM口即串行通讯端口,简称串口】,而TTL、RS-232、RS-485是指的电平标准(电信号--通信协议)

      2)TTL标准是低电平为0,高电平为1(+5V电平)。RS-232标准是正电平为0,负电平为1(±15V电平)
详见点击打开链接

2.串口设置步骤:

(1)串口时钟,GPIO时钟使能-->RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1);

(2)串口复位--->void USART_DeInit(USART_TypeDef* USARTx);--USART_DeInit(USART1); //复位串口
1

(3)GPIO端口模式设置-->GPIO_Init(); 模式设置为GPIO_Mode_AF_PP----【端口复用和重映射很不一样-点击打开链接--------区别:点击打开链接

(4)串口参数初始化--->void USART_Init(USART_TypeDef* USARTx,USART_InitTypeDef*USART_InitStruct); 

1)USART_InitTypeDef
类型的结构体指针:  

USART_InitStructure.USART_BaudRate = bound; //波特率;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为 8 位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None; //无硬件数据流控制,用于两个uart模块之间传输数据
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口  

2)串口数据收发:

USART_DR寄存器发送数据函数:void
USART_SendData(USART_TypeDef* USARTx, uint16_t Data); 

USART_DR寄存器读取串口接收到的数据函数:uint16_t
USART_ReceiveData(USART_TypeDef* USARTx);

3)串口状态读取:

*RXNE(读数据寄存器非空),当该位被置1的时候,就是提示已经有数据被接收到。

*TC(发送完成),当该位被置位的时候,表示USART_DR内的数据已经被发送完成。如果设置了这个位的中断,则会产生中断。

*读取串口状态的函数:FlagStatus
USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
第二个入口参数很重要:RXNE(读数据寄存器非空)以及TC(发送完成)

判断读寄存器是否非空(RXNE),操作库函数:USART_GetFlagStatus(USART1,
USART_FLAG_RXNE);
判断发送是否完成(TC),操作库函数:USART_GetFlagStatus(USART1,
USART_FLAG_TC);

4)串口使能----->USART_Cmd(USART1,
ENABLE);

(5)开启中断并且初始化NVIC-->NVIC_Init();(如果需要开启中断才需要这个步骤)

1)使能串口中断函数:void
USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT,FunctionalState NewState)

*****接收数据的时候产生中断:USART_ITConfig(USART1, USART_IT_RXNE,
ENABLE);//开启中断,接收到数据中断【RXNE位被置位。它表明移位寄存器的内容被转移到RDR。换句话说,数据已经被接收并且可以被读出(包括与之有关的错误标志)------>*如果RXNE=1,上一个有效数据还在接收寄存器RDR上,可以被读出.;;如果RXNE=0,这意味着上一个有效数据已经被读走, RDR已经没有东西可读。当上一个有效数据在RDR中被读取的同时又接收到新的(也就是丢失的)数据时,此种情况可能发生。 】

发送数据结束时(TC,发送完成)产生中断:USART_ITConfig(USART1, USART_IT_TC, ENABLE);

******USART中断请求--标志说明

**TXE---->发送数据寄存器空

**CTS--->CTS标志

**TC--->发送完成

**TXNE--->接收数据就绪可读

**ORE--->检测到数据溢出

**IDLE--->检测到空闲线路

**PE--->奇偶检验错

**LBD--->断开标志

**NE或ORT或FE--->噪声标志,多缓冲通信中的溢出错误和帧错误

2)获取相应的中断状态(判断是哪个中断产生的):ITStatusUSART_GetITStatus(USART_TypeDef*USARTx,
uint16_t USART_IT)

例:判断到底是否是串口发送完成中断 --->USART_GetITStatus(USART1,
USART_IT_TC)

(6)编写中断处理函数--->USARTx_IRQHandler();

(7)串口数据收发:void USART_SendData();//发送数据到串口,DR
  uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据

(8)串口传输状态获取:FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

在主函数中编写UART1串口通信:

[cpp] view
plain copy

#include "stm32f10x.h"//必须加上,不然不能识别时钟函数等宏定义  

#include "LED.h"  

  

  

void USART1_IRQHandler(void)//USART_IT_RXNE:接收到数据,就执行中断服务函数  

{  

<span style="white-space:pre">  </span>//在stm32f10x_usart.c文件中查找功能函数  

<span style="white-space:pre">  </span>if(USART_GetITStatus(USART1,USART_IT_RXNE/*中断标志是什么,此处就应该写什么*/))  

<span style="white-space:pre">  </span>{  

<span style="white-space:pre">      </span>uint16_t res = USART_ReceiveData(USART1); //从串口接收到数据  

<span style="white-space:pre">      </span>USART_SendData(USART1,res);//将数据从串口发出去  

<span style="white-space:pre">      </span>LED0 = ~LED0;  

<span style="white-space:pre">  </span>}  

}  

void my_uart_init(void)  

{  

<span style="white-space:pre">  </span>//参数结构定义--->应该写在函数开头处  

<span style="white-space:pre">  </span>GPIO_InitTypeDef GPIO_InitStruct;  

  USART_InitTypeDef USART1_para;  

  NVIC_InitTypeDef NVIC_InitStruct;  

<span style="white-space:pre">  </span>  

<span style="white-space:pre">  </span>RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);//PA9,PA10  

<span style="white-space:pre">  </span>//端口重映射  

<span style="white-space:pre">  </span>//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);  

<span style="white-space:pre">  </span>//GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);  

<span style="white-space:pre">  </span>USART_DeInit(USART1);//串口复位  

<span style="white-space:pre">  </span>  

<span style="white-space:pre">  </span>//GPIO端口模式设置  

<span style="white-space:pre">  </span>GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//推免输出  

<span style="white-space:pre">  </span>GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;//USART1_TX  

<span style="white-space:pre">  </span>GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  

<span style="white-space:pre">  </span>GPIO_Init(GPIOA,&GPIO_InitStruct);  

  

  

<span style="white-space:pre">  </span>GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入  

<span style="white-space:pre">  </span>GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;//USART1_RX  

<span style="white-space:pre">  </span>//GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  

<span style="white-space:pre">  </span>GPIO_Init(GPIOA,&GPIO_InitStruct);  

<span style="white-space:pre">  </span>  

<span style="white-space:pre">  </span>//串口参数设置  

<span style="white-space:pre">  </span>USART1_para.USART_BaudRate = 9600;  

<span style="white-space:pre">  </span>USART1_para.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  

<span style="white-space:pre">  </span>USART1_para.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;  

<span style="white-space:pre">  </span>USART1_para.USART_Parity = USART_Parity_No;  

<span style="white-space:pre">  </span>USART1_para.USART_StopBits = USART_StopBits_1;  

<span style="white-space:pre">  </span>USART1_para.USART_WordLength = USART_WordLength_8b;  

<span style="white-space:pre">  </span>USART_Init(USART1,&USART1_para);  

<span style="white-space:pre">  </span>  

<span style="white-space:pre">  </span>//使能串口  

<span style="white-space:pre">  </span>USART_Cmd(USART1,ENABLE);  

<span style="white-space:pre">  </span>  

<span style="white-space:pre">  </span>//中断配置  

<span style="white-space:pre">  </span>USART_ITConfig(USART1,USART_IT_RXNE/*接收到数据 就出发中断*/,ENABLE);//触发中断标志  

<span style="white-space:pre">  </span>  

<span style="white-space:pre">  </span>//开启中断并初始化  

<span style="white-space:pre">  </span>NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;//串口中断函数  

<span style="white-space:pre">  </span>NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;  

<span style="white-space:pre">  </span>NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;//优先级  

<span style="white-space:pre">  </span>NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;//子优先级  

<span style="white-space:pre">  </span>NVIC_Init(&NVIC_InitStruct);  

}  

  

  

<span style="white-space:pre">  </span>  

int main(void)  

{  

<span style="white-space:pre">  </span>LED_init();  

<span style="white-space:pre">  </span>LED0 = 1;  

<span style="white-space:pre">  </span>NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组  

<span style="white-space:pre">  </span>my_uart_init();  

<span style="white-space:pre">  </span>while(1);  

<span style="white-space:pre">  </span>  

}  

回车:0x0d;换行:0x0a

使用串口2源代码:点击打开链接

printf("\r\n\r\n");---->将内容发送到主串口-【可在usart.c中修改】
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: