您的位置:首页 > 其它

串口初始化捉虫记

2018-02-06 22:24 274 查看
第一篇博客,记录一个找到BUG结果BUG变功能的悲惨的故事.

最近在做一个单片机的小项目,使用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


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  学习