串口初始化捉虫记
2018-02-06 22:24
274 查看
第一篇博客,记录一个找到BUG结果BUG变功能的悲惨的故事.
最近在做一个单片机的小项目,使用STM8的单片机,用到串口收发数据.前期图方便,直接用了个现成项目的模板,把硬件驱动都写好并测试成功了,然后看着莫名其妙的项目名,想着为了改个名,干脆重新新建个工程吧.没想到,竟因此发现了个BUG.
原先程序在main.c里面对串口进行初始化,串口初始化为
旧工程里运行良好,但一直到新的工程里面后,总是卡在
出不来.单步执行后发现是在
到这里比较有经验的人可能已经看出来问题在哪里了,但是我还是太嫩了点,只得继续找下去.
设置串口中断的函数在STM8的官方库里
运行的时候问题就出在
这条语句上.执行到这句后,就跳转到断言函数里去了
落在了这个无限循环里去了.怪不得会卡着.可是为什么会掉到这里呢?
先百度了下,这是个啥
若
的执行结果为否,则会跳转到
中.到这里,比较有点经验的人可能已经看出来问题在哪里了,但是我还是太嫩了点,只得继续找下去.
既然一直跳到
那肯定是
为否了,同时尝试了下,旧工程里,这条语句并没有执行.而新工程,注释掉这句,也可以正常运行.但为了发现真正的原因,我还要继续找下去.
判断的是
的值,
首先测试其功能是否正常,
先打印输出UART2_IT的值,显示为0x0255,
为
看了下初始化函数里的,输入的确实是
直接输入数值进去
同样有问题,于是看
的定义
也就是说,只要输入为
之一,则为为1,否则就会有问题
而我输入的是
并不在上面七个之中.
原来
找了半天,答案就在头顶上.
此函数可输入的之值仅为
这7个,我一开始写的
并不在此列.虽然这么也初始化成功,功能居然也是正常,但实际是出错了的.
当修改为
之后,新工程运行正常.
我再搜
而
我试了很久,并没有找到关闭的办法...
都说注释掉
然而对这句,我试了各种方式,依然不会跳过
最近在做一个单片机的小项目,使用STM8的单片机,用到串口收发数据.前期图方便,直接用了个现成项目的模板,把硬件驱动都写好并测试成功了,然后看着莫名其妙的项目名,想着为了改个名,干脆重新新建个工程吧.没想到,竟因此发现了个BUG.
原先程序在main.c里面对串口进行初始化,串口初始化为
void UART_Init() { GPIO_Init(GPIOD,GPIO_PIN_6,GPIO_MODE_IN_PU_NO_IT); UART2_Init(19200,UART2_WORDLENGTH_8D,UART2_STOPBITS_1,UART2_PARITY_NO,UART2_SYNCMODE_CLOCK_DISABLE,UART2_MODE_TXRX_ENABLE);//19200,8,n,1,none,RT UART2_ITConfig(UART2_IT_RXNE,ENABLE);//接收非空中断 UART2_Cmd(ENABLE); }
旧工程里运行良好,但一直到新的工程里面后,总是卡在
UART_Init();
出不来.单步执行后发现是在
UART2_ITConfig(UART2_IT_RXNE,ENABLE);//接收非空中断
到这里比较有经验的人可能已经看出来问题在哪里了,但是我还是太嫩了点,只得继续找下去.
设置串口中断的函数在STM8的官方库里
void UART2_ITConfig(UART2_IT_TypeDef UART2_IT, FunctionalState NewState) { uint8_t uartreg = 0, itpos = 0x00; /* Check the parameters */ assert_param(IS_UART2_CONFIG_IT_OK(UART2_IT)); assert_param(IS_FUNCTIONALSTATE_OK(NewState)); /* Get the UART2 register index */ uartreg = (uint8_t)((uint16_t)UART2_IT >> 0x08); ................................
运行的时候问题就出在
assert_param(IS_UART2_CONFIG_IT_OK(UART2_IT));
这条语句上.执行到这句后,就跳转到断言函数里去了
void assert_failed(u8* file, u32 line) { /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* Infinite loop */ while (1) { } }
落在了这个无限循环里去了.怪不得会卡着.可是为什么会掉到这里呢?
先百度了下,这是个啥
assert_param()的作用就是用来判断传递给函数的参数是否是有效值。
若
assert_param()
的执行结果为否,则会跳转到
assert_failed()
中.到这里,比较有点经验的人可能已经看出来问题在哪里了,但是我还是太嫩了点,只得继续找下去.
既然一直跳到
assert_failed()
那肯定是
assert_param()
为否了,同时尝试了下,旧工程里,这条语句并没有执行.而新工程,注释掉这句,也可以正常运行.但为了发现真正的原因,我还要继续找下去.
assert_param(IS_UART2_CONFIG_IT_OK(UART2_IT));
判断的是
IS_UART2_CONFIG_IT_OK(UART2_IT)
的值,
首先测试其功能是否正常,
先打印输出UART2_IT的值,显示为0x0255,
typedef enum { UART2_IT_TXE = (uint16_t)0x0277, /**< Transmit interrupt */ UART2_IT_TC = (uint16_t)0x0266, /**< Transmission Complete interrupt */ UART2_IT_RXNE = (uint16_t)0x0255, /**< Data Register Not Empty interrupt */ UART2_IT_IDLE = (uint16_t)0x0244, /**< Idle line detected interrupt */ UART2_IT_OR = (uint16_t)0x0235, /**< OverRun error interrupt */ UART2_IT_PE = (uint16_t)0x0100, /**< Parity Error interrupt */ UART2_IT_LBDF = (uint16_t)0x0346, /**< LIN Break Detection interrupt */ UART2_IT_LHDF = (uint16_t)0x0412, /**< LIN Header Detection interrupt*/ UART2_IT_RXNE_OR = (uint16_t)0x0205 /*!< Receive/Overrun interrupt */ } UART2_IT_TypeDef;
为
UART2_IT_RXNE
看了下初始化函数里的,输入的确实是
UART2_IT_RXNE
直接输入数值进去
IS_UART2_CONFIG_IT_OK(0x0255)
同样有问题,于是看
IS_UART2_CONFIG_IT_OK()
的定义
#define IS_UART2_CONFIG_IT_OK(Interrupt) \ (((Interrupt) == UART2_IT_PE) || \ ((Interrupt) == UART2_IT_TXE) || \ ((Interrupt) == UART2_IT_TC) || \ ((Interrupt) == UART2_IT_RXNE_OR ) || \ ((Interrupt) == UART2_IT_IDLE) || \ ((Interrupt) == UART2_IT_LHDF) || \ ((Interrupt) == UART2_IT_LBDF))
也就是说,只要输入为
UART2_IT_PE UART2_IT_TXE UART2_IT_TC UART2_IT_RXNE_OR UART2_IT_IDLE UART2_IT_LHDF UART2_IT_LBDF
之一,则为为1,否则就会有问题
而我输入的是
UART2_IT_RXNE
并不在上面七个之中.
/** * @brief Enables or disables the specified UART2 interrupts. * @param UART2_IT specifies the UART2 interrupt sources to be enabled or disabled. * This parameter can be one of the following values: * - UART2_IT_LBDF: LIN Break detection interrupt * - UART2_IT_LHDF: LIN Break detection interrupt * - UART2_IT_TXE: Tansmit Data Register empty interrupt * - UART2_IT_TC: Transmission complete interrupt * - UART2_IT_RXNE_OR: Receive Data register not empty/Over run error interrupt * - UART2_IT_IDLE: Idle line detection interrupt * - UART2_IT_PE: Parity Error interrupt * @param NewState new state of the specified UART2 interrupts. * This parameter can be: ENABLE or DISABLE. * @retval None */ void UART2_ITConfig(UART2_IT_TypeDef UART2_IT, FunctionalState NewState) {
原来
找了半天,答案就在头顶上.
此函数可输入的之值仅为
* - UART2_IT_LBDF: LIN Break detection interrupt * - UART2_IT_LHDF: LIN Break detection interrupt * - UART2_IT_TXE: Tansmit Data Register empty interrupt * - UART2_IT_TC: Transmission complete interrupt * - UART2_IT_RXNE_OR: Receive Data register not empty/Over run error interrupt * - UART2_IT_IDLE: Idle line detection interrupt * - UART2_IT_PE: Parity Error interrupt
这7个,我一开始写的
UART2_IT_RXNE
并不在此列.虽然这么也初始化成功,功能居然也是正常,但实际是出错了的.
当修改为
UART2_IT_RXNE_OR
之后,新工程运行正常.
我再搜
assert_param
又看到了这句话assert_param语句的作用是检测函数的参数是否符合该函数的要求,如果参数出错,会跳转到assert_failed,此时,可以这么定义
void assert_failed(uint8_t* file, uint32_t line) { printf("Wrong parameters value: file %s on line %d\r\n", file, line); while(1); } 作用是可以输出出错的文件名称和行号。
而
assert_param语句是用于程序开发的时候,调试用的检测语句。默认是不开启的,你可以无视它的存在。但是,当你在调试程序的时候,可以打开这个检测机制,调试完了再关闭。
我试了很久,并没有找到关闭的办法...
都说注释掉
#define USE_FULL_ASSERT (1)
然而对这句,我试了各种方式,依然不会跳过
assert_param
相关文章推荐
- Linux串口驱动分析初始化
- STM32F103和STM32F105在串口初始化的区别
- C#中初始化串口的函数定义与数据接收代码片段
- u-boot串口和stdio、console初始化及相关操作详解<一>
- u-boot串口初始化全过程
- avr单片机USART串口通讯初始化配置说明
- 串口驱动程序设计详解---串口初始化(上)
- 一段串口的api初始化代码
- 串口驱动之初始化 (一)
- Main.C中 IO口,中断及串口初始化
- S 串口编程 详解3 串口的初始化、打开/关闭
- 汇编级UART串口初始化与打印
- MAX32630/MAX32625学习:UART串口初始化、发送函数,接收中断及实验(绝对实用)
- acpi 表中对spcr的parse来初始化串口
- s3c6410 串口初始化
- Zigbee串口初始化的解析1
- u-boot串口和stdio、console初始化及相关操作详解<一>
- u-boot串口和stdio、console初始化及相关操作详解<三>
- LPC2294的uclinux启动过程分析--串口初始化过程
- stm32LCD必须进行串口初始化