在调试Modubus协议时需要用到串口的奇偶校验位,但是平时用串口时很少用到奇偶校验位,网上搜相关的历程也很少,将自己写的串口奇偶校验代码分享上来方便以后查阅。
如果用库函数的话,添加奇偶检验位就很简单,在初始化串口的时候,将默认的无校验位修改为奇校验或者偶校验,同时将数据位设置为9位。
串口初始化代码如下:
#include "uart2.h"
#define CHECK_NONE_ONE_STOP 0 //无校验位 1个停止位 1有效 0 无效
#define CHECK_NONE_TWO_STOP 1 //无校验位 2个停止位 1有效 0 无效
#define CHECK_EVEN 1 //偶数校验 1有效 0 无效
#define CHECK_ODD 0 //奇数校验 1有效 0 无效
void uart2_init( u32 baud )
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOA, &GPIO_InitStructure );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOA, &GPIO_InitStructure );
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init( &NVIC_InitStructure );
USART_InitStructure.USART_BaudRate = baud;
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位8位
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //1位停止位
#if(CHECK_EVEN == 1) //如果定义了偶校验 数据位长度要改为9位
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_Parity = USART_Parity_Even;
#endif
#if(CHECK_ODD == 1) //如果定义了偶校验 数据位长度要改为9位
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_Parity = USART_Parity_Odd;
#endif
#if(CHECK_NONE_ONE_STOP==1) //停止位为 一位
USART_InitStructure.USART_StopBits = USART_StopBits_1;
#endif
#if(CHECK_NONE_TWO_STOP==1) //停止位为 两位
USART_InitStructure.USART_StopBits = USART_StopBits_2;
#endif
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init( USART2, &USART_InitStructure );
USART_ITConfig( USART2, USART_IT_RXNE, ENABLE );
USART_Cmd( USART2, ENABLE );
}
void USART2_IRQHandler( void )
{
u16 tem = 0;
if( USART_GetITStatus( USART2, USART_IT_RXNE ) != RESET )
{
tem = USART_ReceiveData( USART2 );
USART_SendData( USART2, tem );
}
}
通过宏定义来设置是否使用奇偶校验位,停止位为1位还是2位。如果使用了奇偶校验时,要将数据位设置为9位。设置好之后就不用管了,具体校验工作由硬件来完成。
在串口中断函数中实现的功能是,将串口2接收到的数据通过串口2发送出去。
在宏定义中设置为2个停止位,偶校验。
串口测试效果如下:
如果串口助手设置和单片机发送不一致时,接收到的数据就为乱码。
源码地址https://download.csdn.net/download/qq_20222919/12921508
在调试Modubus协议时需要用到串口的奇偶校验位,但是平时用串口时很少用到奇偶校验位,网上搜相关的历程也很少,将自己写的串口奇偶校验代码分享上来方便以后查阅。
如果用库函数的话,添加奇偶检验位就很简单,在初始化串口的时候,将默认的无校验位修改为奇校验或者偶校验,同时将数据位设置为9位。
串口初始化代码如下:
#include "uart2.h"
#define CHECK_NONE_ONE_STOP 0 //无校验位 1个停止位 1有效 0 无效
#define CHECK_NONE_TWO_STOP 1 //无校验位 2个停止位 1有效 0 无效
#define CHECK_EVEN 1 //偶数校验 1有效 0 无效
#define CHECK_ODD 0 //奇数校验 1有效 0 无效
void uart2_init( u32 baud )
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOA, &GPIO_InitStructure );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init( GPIOA, &GPIO_InitStructure );
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init( &NVIC_InitStructure );
USART_InitStructure.USART_BaudRate = baud;
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位8位
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //1位停止位
#if(CHECK_EVEN == 1) //如果定义了偶校验 数据位长度要改为9位
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_Parity = USART_Parity_Even;
#endif
#if(CHECK_ODD == 1) //如果定义了偶校验 数据位长度要改为9位
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_Parity = USART_Parity_Odd;
#endif
#if(CHECK_NONE_ONE_STOP==1) //停止位为 一位
USART_InitStructure.USART_StopBits = USART_StopBits_1;
#endif
#if(CHECK_NONE_TWO_STOP==1) //停止位为 两位
USART_InitStructure.USART_StopBits = USART_StopBits_2;
#endif
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init( USART2, &USART_InitStructure );
USART_ITConfig( USART2, USART_IT_RXNE, ENABLE );
USART_Cmd( USART2, ENABLE );
}
void USART2_IRQHandler( void )
{
u16 tem = 0;
if( USART_GetITStatus( USART2, USART_IT_RXNE ) != RESET )
{
tem = USART_ReceiveData( USART2 );
USART_SendData( USART2, tem );
}
}
通过宏定义来设置是否使用奇偶校验位,停止位为1位还是2位。如果使用了奇偶校验时,要将数据位设置为9位。设置好之后就不用管了,具体校验工作由硬件来完成。
在串口中断函数中实现的功能是,将串口2接收到的数据通过串口2发送出去。
在宏定义中设置为2个停止位,偶校验。
串口测试效果如下:
如果串口助手设置和单片机发送不一致时,接收到的数据就为乱码。
源码地址https://download.csdn.net/download/qq_20222919/12921508
举报