串口通信
波特率:串口通信的速率,串口通信要以一个相同速率进行通信,STM32不用计算波特率
起始位:标志一个数据帧的开始,固定为低电平
数据位:数据帧的有效载荷,1为高电平,0为低电平,低位先行
校验位:用于数据验证,根据数据位计算得来
停止位:用于数据帧间隔,固定为高电平
传输数据
例:发送0x55
数据帧
STM32串口有两种字长的数据传输模式,8位和9位。9位字长的传输模式下,空闲时候高电平,当有数据要传输时,起始位置0,数据从低位开始一位一位发送,发送完成后第9位有个校验位。校验位可选择奇校验,偶校验和无校验。如果选择奇校验发送的数据中有奇数个1,那么奇校验位为0。如果发送的数据中有偶数个1,那么奇校验位为1。
发送数据时,发送数据后会补校验位,确保1的个数和校验模式相同。接收数据时,验证数据位和校验位1的个数,与校验模式相同则无误。
串口引脚
串口发送
串口发送实际上是对发送数据寄存器(TDR)进行写入。当检测到有数据写入时,就开始检测移位寄存器是否有数据在进行移位,如果没有,数据从TDR就发送至移位寄存器。只要数据移动到移位寄存器后,会产生一个TXE发送寄存器空标志位,该位描述如下。当TXE被置1,代表TDR目前为空,那么就可以在TDR写入下一个数据了。即发送下一个数据。
串口接收
数据从RX引脚通向接收移位寄存器,当数据移位完成后,数据将转移到接收数据寄存器(RDR)中,产生一个RXNE接收寄存器空标志位。数据全部移入RDR后,RXNE置1。当被置1后,数据就可以被读出。接收移位寄存器开始移入下一个数据。
配置串口通信
串口通信配置过程
串口发送初始化
由上面串口通信过程可知,初始化过程要配置GPIO,此次选择PA9作为TX引脚,PA10作为RX引脚。
配置GPIOA
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);
配置串口发送
USART_BaudRate 串口通信使用的波特率 一般是9600或者是115200,这里我们给9600。
USART_HardwareFlowControl 是否选择硬件流触发,一般这个我们也不选,所以选择无硬件流触发。
USART_Mode 串口的模式,发送模式还是接收模式,还是两者都有。这里选择发送模式。
USART_Parity 校验位,可以选择奇偶校验和不校验。这里选择无校验。
USART_StopBits 停止位 有1、0.5、2位,我们这里选1位停止位。
USART_WordLength 数据位 有8位和9位可以选择,这里选择8位。
USART_Cmd 开启UASRT
RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1 ,ENABLE);
USART_InitTypeDef USART_Initstructure;
USART_Initstructure.USART_BaudRate=9600;
USART_Initstructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_Initstructure.USART_Mode=USART_Mode_Tx;
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_Cmd (USART1,ENABLE);
串口接收初始化
配置GPIOA
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);
配置串口初始化
注意:只需要添加Rx引脚即可,其它配置和串口发送一样
USART_Initstructure.USART_Mode=USART_Mode_Tx | USART_Mode_Rx;
配置中断
USART_ITConfig (USART1 ,USART_IT_RXNE ,ENABLE);
NVIC_PriorityGroupConfig (NVIC_PriorityGroup_2 );
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
串口发送
发送一个数据
这里注意判断RXE是否置1,没有的话一直发送。发送完成后RXE置1
void Serial_SendByte(uint8_t Byte)
{
USART_SendData (USART1,Byte);
while(USART_GetFlagStatus (USART1 ,USART_FLAG_TXE )==RESET);
}
发送一个数组
void Serial_SendArray(uint8_t *Array ,uint16_t Lenght)
{
uint8_t i;
for(i=0;i<Lenght ;i++)
{
Serial_SendByte(Array[i]);
}
}
发送一串字符
void Serial_SendString(char *String)
{
uint8_t i;
for(i=0;String[i]!='\0';i++)
{
Serial_SendByte(String[i]);
}
}
发送一串数字
uint32_t Serial_Pow(uint32_t X , uint32_t Y)
{
uint32_t Result=1;
while(Y--)
{
Result *=X;
}
return Result ;
}void Serial_SendNumber(uint32_t Number,uint8_t Lenght)
{
uint8_t i;
for(i=0;i<Lenght ;i++)
{
Serial_SendByte(Number/Serial_Pow(10,Lenght -i-1)%10+0x30);
}
}
串口接收
查询数据
uint32_t Serial_ReceiveByte(void)
{
uint16_t RxData;
if(USART_GetFlagStatus (USART1 ,USART_FLAG_RXNE )==SET)
{
RxData=USART_ReceiveData (USART1 );
}
return RxData ;
}
使用中断
uint8_t Serial_GetFlag(void)
{
if(Serial_RxFlag ==1)
{
Serial_RxFlag =0;
return 1;
}
return 0;
}
uint8_t Serial_GetRxData(void)
{
return Serial_RxData;
}
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1 ,USART_IT_RXNE )==SET )
{
Serial_RxData =USART_ReceiveData (USART1 );
Serial_RxFlag =1;
USART_ClearITPendingBit(USART1 ,USART_IT_RXNE );
}
}