文章目录
一、STM32 USART
USART的全称是universal synchronous asynchronous receiver and transmitte,中文名叫做通用同步异步收发器。USART是一种非常重要的通信协议,单片机和很多的外设的通信都是用的串口通信,这是一种全双工的异步通信,发送端称为TXD(Transmit Data),接收端称为RXD(Receive Data)。对于串口通信最重要的就是五个量,起始位、数据位,停止位,校验位以及波特率。
波特率是指每秒传输的数据位数,这是一个非常重要的参数,直接关系到能否正常进行串口通信。波特率是通信双方约定好的一个数值,我理解双方多久检测一下特殊的标志位,如果两边的波特率不同的话,就会出现各种各样的问题。
二、STM32串口通信设置
我们在STM32上使用串口通信时,要把起始位、数据位、校验位以及波特率设置好。话不多说,这就来通过代码来学习STM32的串口通信。
void MyUsart_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;//定义GPIO初始化结构体
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);//使能串口时钟和GPIO时钟
USART_DeInit(USART1);//复位串口
//
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);//初始化GPIO9
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);//初始化GPIO10
//设置串口参数
USART_InitStruct.USART_BaudRate=115200;
USART_InitStruct.USART_WordLength=USART_WordLength_8b;//8位数据位
USART_InitStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//发送和接收模式
USART_InitStruct.USART_Parity=USART_Parity_No;//没有校验位
USART_InitStruct.USART_StopBits=USART_StopBits_1;//1位停止位
USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_Init(USART1,&USART_InitStruct);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//设置串口接收中断
USART_Cmd(USART1,ENABLE);//使能串口
//设置中断
NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStruct);
//开启中断
}
在这段代码中,设置8位数据位,一位停止位,没有数据位,这是很常用的一种组合,然后把波特率设置成了115200。下面就来总结一下串口的设置方法。
- 使能相应的串口时钟和GPIO时钟
- 初始化串口的TXD和RXD所在的GPIO,发送端设置为复用推挽输出,接收端设置为浮空输入
- 初始化串口,设置串口的数据位(USART_WordLength)、停止位(USART_StopBits)、校验位(USART_Parity)和波特率(USART_BaudRate)。
- 使能串口
- 串口中断分为发送中断和接收中断,如果设置了中断,还要设置相应的中断参数。
串口的设置核心就是设置数据位,停止位,校验位以及波特率,通信双方的这四个参数一定要完全一样才能实现串口通信,双方通过导线交叉连接,TXD接RXD,RXD接TXD。
虽然串口设置很简单,但是往往在使用串口通信时要通过上位机调试很多次才能排除一个个小错误,确保发送的数据可以被完好无损地收到。所以我觉得串口数据的发送和接收才是重点。
三、串口数据的发送
1.printf发送
在使用STM32标准库时,可以用printf函数来发送字符串,这是非常方便的,下面就来看看怎么通过这种方式发送数据吧
首先写重映射函数
//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR = (u8) ch;
return ch;
}
#endif
这一窜代码中选择了串口号,有了这一段代码,就可以直接使用printf(“qwer”)来通过串口发送字符串。
2.使用官方的标准库函数USART_SendData(串口号,数据);
官方的**USART_SendData(USART_TypeDef* USARTx, uint16_t Data);**串口发送函数每次只能发送一个字节,原理就是直接往TDR寄存器写入要发送的字节,如果要用这个发送一个字符串,就要写一个发送函数。
void Send_data(USART_TypeDef * USARTx,u8 *s)
{
while(*s!='')
{
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC )==RESET);
USART_SendData(USARTx,*s);
s++;
}
}
这个发送函数是把字符串中的每个字符分开发送,直到字符串结束。
四、串口数据接收
有发送就会有接收,串口接收数据是一个字节一个字节地接收,如果设置了接收中断,那就是收到一个字节就进入一次中断。
下面就来看一个很经典的串口接收函数
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
OSIntEnter();
#endif
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res =USART_ReceiveData(USART1); //读取接收到的数据
if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
else USART_RX_STA|=0x8000; //接收完成了
}
else //还没收到0X0D
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
}
}
}
}
在串口接收中断中处理接收到的数据,这段程序中规定发送的数据一定要以0x0a 0x0d结尾,如果是就把接收到的数据放在定义好的接收数组中,然后我们可以在主函数中对数组中接收到的数据进行处理。
五、UART和USART的区别
USART是指单片机的一个端口模块,可以根据需要配置成同步模式(SPI,I2C),也可以将其配置为异步模式,后者就是UART。所以说UART姑且可以称之为一个与SPI,I2C对等的“协议”,而USART则不是一个协议,而是更应该理解为一个实体。
(摘自https://blog.csdn.net/weixin_40774605/article/details/88398709)
总结
串口的设置是设置起始位、数据位、校验位、停止位和波特率,通信的双方要设置相同的参数,并且硬件硬件交叉连接。串口发送函数可以是printf函数,接收函数可以根据具体的数据格斯自行定义,但应该知道每接收到一个字节都可以通过USART_ReceiveData读出。关于串口的部分就先写到这里,后续会进行补充和完善,有错误的地方请指出。