最近,在做基于stm32f401串口的ModBus协议通信,遇到了stm32串口发送数据的问题。花了一整天去查找问题,从ModBus协议格式、调度算法到串口配置,最终终于把问题解决,记录下来。
问题描述:
ModBus协议中配置stm32f401串口为奇校验,8位数据位,1位停止位,程序如下:
void uart_init( u32 bound )
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE );//使能USART1,GPIOA时钟
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init( GPIOA, &GPIO_InitStructure ); //初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init( GPIOA, &GPIO_InitStructure ); //初始化GPIOA.10
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; //抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能
NVIC_Init( &NVIC_InitStructure ); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
#ifdef EN_FREE_MODBUS //支持ModBus
USART_InitStructure.USART_Parity = USART_Parity_Even ;//奇校验,与freeModbus中设置一致
#else
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
#endif
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
USART_Init( USART1, &USART_InitStructure ); //初始化串口1
USART_ITConfig( USART1, USART_IT_RXNE, ENABLE ); //开启串口接受中断
USART_Cmd( USART1, ENABLE ); //使能串口1
}
采用串口助手接收Modbus发送来的数据,最高位基本都是出错的,有的本来是1收到的是0,有的本来是0收到的是1,只有极少数数据正确。通过分析Modbus协议,未发现问题;串口助手配置也没有问题。最后在网上查到的解决办法,并仔细阅读了stm32的datasheet,有如下表述:
M位PCE位 USART帧
0 0 | 起始位 | 8位数据|停止位 |
0 1 | 起始位 | 7位数据|奇偶检验位 | 停止位 |
1 0 | 起始位 | 9位数据 | 停止位 |
1 1 | 起始位 | 8位数据 | 奇偶检验位 | 停止位 |
其中,M位为1代表UART库函数中设置为9位数据,M位为0代表设置为8位数据;PCE位为1代表有奇偶校验,为0代表无校验。可以看出,stm32在设置奇偶校验后将校验位算到了数据位里。因此,在ModBus设置为奇校验后,为了保证数据为8位,需要设置数据位长度为9,即将数据位数设置语句改为下面即可:
/*STM32中,设置的数据长度包含校验位。
若设置了奇校验或偶校验,则校验位会占1位。这时要想数据为8位(一般的串口助手直接设置为8位),下面的字长需要设为9位。
若没有设置奇偶校验,则直接设为8位即可。*/
if( USART_InitStructure.USART_Parity == USART_Parity_No )
{
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
}
else
{
USART_InitStructure.USART_WordLength = USART_WordLength_9b;//字长为9位数据格式
}
上一篇:STM32串口发送数据和接收数据方式总结
下一篇:使用STM32的串口进行大量数据传输
推荐阅读
史海拾趣
AdTech公司一直注重创新,不断投入研发资源以推出新产品和解决方案。公司通过优化芯片结构设计、提升器件封装技术等手段,不断提升QCL的性能和稳定性。此外,公司还积极探索QCL在新能源、环保等领域的应用潜力,开发出了一系列具有创新性和实用性的产品。这些创新成果不仅提升了公司的核心竞争力,也为行业的发展注入了新的活力。
DATATRONICS公司自成立以来,一直致力于电子技术的研发与创新。某年,公司研发团队成功突破了一项关键技术瓶颈,开发出了一款高效能的数据处理芯片。这款芯片以其卓越的性能和稳定性,迅速获得了市场的认可。DATATRONICS借此机会,进一步扩大了产品线,提高了市场竞争力。
为了进一步提升竞争力,Alan Industries Inc.积极寻求与其他企业的战略合作。公司与多家知名供应商建立了长期稳定的合作关系,确保了原材料的稳定供应和成本控制。同时,公司还通过并购和投资等方式,整合了产业链上下游资源,形成了完整的产业生态圈。这些战略举措使得公司在市场竞争中更具优势,实现了快速发展。
随着多媒体技术的快速发展,专业影音产品的市场需求逐渐增长。Aten International紧跟市场趋势,投入大量研发资源,推出了一系列专业影音产品,包括高清视频切换器、音频分配器等。这些产品以其高品质、高稳定性受到了市场的广泛认可,为Aten International在电子行业树立了良好的口碑。
在电子行业中,标准化建设对于提升产品质量和企业竞争力具有重要意义。Aten International深知标准化建设的重要性,因此在产品研发和生产过程中始终坚持高标准、严要求。公司还积极参与国际标准化组织的活动,推动相关标准的制定和完善。正是凭借在标准化建设方面的卓越表现,Aten International赢得了业界的高度认可和广泛赞誉。
以上五个故事虽然基于虚构,但它们都反映了Aten International在电子行业发展的真实情况。这些故事展示了公司在技术创新、市场拓展、标准化建设等方面的努力和成就,也体现了Aten International在电子行业中的领先地位和卓越贡献。
在竞争激烈的电子行业中,品质控制和品牌建设至关重要。Deutsch公司深知这一点,因此始终将品质控制和品牌建设作为公司的重要任务。公司建立了严格的质量管理体系,确保产品的每一个细节都符合高标准。同时,通过精心策划的品牌推广活动,Deutsch公司的品牌形象逐渐深入人心。这些努力不仅提升了公司的市场地位,也增强了客户对公司的忠诚度。
各位好! 有问题想请教一下,三极管手册上的 “ β ”的范围是什么意思? 比如 C9013的数据手册上 写着C9013H的 “ H ” 是指“ β ”的范围是 144-202 不知道这是什么意思,是指: 1.一个三极管,由于在不同的极间电压,输出特性曲线不是完全 ...… 查看全部问答∨ |
本帖最后由 paulhyde 于 2014-9-15 09:37 编辑 阻尼振荡的两种。 直观地看波形,只有欠阻尼有振荡,其幅度逐渐减小。过阻尼看波形根本没有振荡,在冲击函数(狄拉克函数)作用下,波形先上升后下降到零,没有反复,但也叫振荡。 此二者之间,恰好 ...… 查看全部问答∨ |
不要开上司的玩笑 你一定要记住这句话:上司永远是上司,不要期望在工作岗位上能和他成为朋友。即便你们以前是同学或是好朋友,也不要自恃过去的交情与上司开玩笑,特别是在有别人在场的情况下,更应格外注意。 不要以同事的缺点或不足 ...… 查看全部问答∨ |
|
我想识别的是个usb加密锁 if (dbhdr && dbhdr->dbcd_devicetype == DBT_DEVTYP_VOLUME) 这个是用来识别usb硬盘的 设备类型有以下五类: DBT_DEVTYP_DEVICEINTERFACE DBT_DEVTYP_HANDLE DBT_DEVTYP_OEM DBT_DEVTYP_PORT DBT_DEVT ...… 查看全部问答∨ |
|
本人刚买了个友善之臂的mini2440开发板。按他们的用户说明中,建立好“超级终端”后,打开电源,从NOR FLASH启动。在超级终端中输入每一个命令,都是“Could not found \'*\' command”的错误提示。到底什么原因,莫非Supervivi没有烧写吗?希望知 ...… 查看全部问答∨ |
|