ashwatermelon

ashwatermelon

【学习笔记】stm32单片机USART串口

最近学了 stm32 的串口通信。
串口在之前学 51 的时候用过,不过差不多忘干净了(悲)
那么开始复习串口通信。

(一)什么是 USART#

串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。
单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大地扩展了单片机的应用范围,增强了单片机系统的硬件实力。
其通信方式为异步全双工,异步是指通信双方间没有时钟线相连,需要预先设置好波特率(传输频率);全双工是指通信双方都可以发送和接收信号,互不干扰。
USART 串口通信有两条线,一条是 TXD,用于发送信号;一条是 RXD,用于接收信号。双方的 TXD 与对方的 RXD 交叉相连。(图片莫名奇妙传不上来,算了)
USART 发送的一个完整的信息包括:起始位、数据位、校验位、停止位,其中,数据位跟校验位总共有 8 或者 9 位位,校验位只有一位,我们可以通过改变停止位的长度来改变发送频率,不过一般选择 8 位无校验,或者 9 位校验,停止位长度 1 位就可以了。

(二)代码配置#

stm32 的库函数中有专门的 USART 函数,所以配置过程可比 51 的简单多了。
代码如下:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure);

USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate=9600; USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
USART_InitStructure.USART_Parity=USART_Parity_No;
USART_InitStructure.USART_StopBits=USART_StopBits_1;
USART_InitStructure.USART_WordLength=USART_WordLength_8b; USART_Init(USART1,&USART_InitStructure);

USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; NVIC_Init(&NVIC_InitStructure);

USART_Cmd(USART1,ENABLE);
我们只要开启时钟初始化引脚后用 USART_Init 初始化 USART(波特率 9600,8 位不校验),然后再用 USART_ITConfig 开启中断,最后配置 NVIC 并启动串口就可以了。

(三)发送与接收信号#

发送信号很简单我们只要用 USART_SendData 函数就可以了:
void Serial_SendByte(uint8_t Data)
{
USART_SendData(USART1,Data);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
}

而在这个的基础上,我们还可以封装出发送字符串、发送数字的函数,比如下面这个发送字符串的函数:
void Serial_SendString(uint8_t*Data)
{
int j = 0;
for(j=0;Data[j]!='\0';j++)
{
Serial_SendByte(Data[j]);
}
}

而接收数据则需要用中断,代码如下:
void USART1_IRQHandler()
{
while(USART_GetITStatus(USART1,USART_IT_RXNE)==RESET);
SerialRXFlag=1;
SerialRXData=USART_ReceiveData(USART1);
}

(四)串口收发数据包#

其实就是让串口收发某种特定格式的内容,比如数据包包头为 0xFF,包尾为 0xFE,代码大致如下:
void Serial_Sendpacket()
{
Serial_SendByte(0xFF);
Serial_SendArray(SerialTXPacket,4);
Serial_SendByte(0xFE);
}

void USART1_IRQHandler()
{
static int pRXPacket = 0;
static uint8_t RxState = 0;
while(USART_GetITStatus(USART1,USART_IT_RXNE)==RESET);
uint8_t RXData = 0;
RXData = USART_ReceiveData(USART1);
switch (RxState)
{
case 0:
if (RXData == 0xFF)
{
RxState = 1;
pRXPacket = 0;
}
break;
case 1:
SerialRXPacket[pRXPacket] = RXData;
pRXPacket++;
if (pRXPacket >= 4)
{
RxState = 2;
}
break;
case 2:
if (RXData == 0xFE)
{
RxState = 0;
SerialRXFlag=1;
}
break;
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}

USART 的内容大概就这么多,说不上多复杂,因为函数库已经把我们本来需要配置的一堆东西都做了。

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。