打印
[STM32F1]

stm32f101c8t6串口中断问题,分不多,全给了

[复制链接]
1220|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
羊斩熊|  楼主 | 2016-3-30 09:39 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
硬件:stm32f101c8t6 软件:keil
问题:用USART3发送命令来控制条形码扫描模块,未开发送中断,只开了接收中断,但是单步发现单片机工作时在发送命令时进入了串口3中断,然后退出进入退出进入...无法进入主循环。刚测试时又发现,系统刚上电时,程序可以跑通,只是当扫描到条形码的时候又会死掉。然后按复位键程序也是进入死循环。用串口助手检测USART3发现刚上电时条形码扫描模块的2条初始化命令能够发送出去,但是复位后往往只能发送第一条。硬件电路检查过好几遍,应该没有问题的。
下面看详细代码:
1、时钟,用到GPIOA,B USART3,AFIO等
void RCC_Configuration(void)
{
  ErrorStatus HSEStartUpStatus;  
  RCC_DeInit();
  RCC_HSEConfig(RCC_HSE_ON);
  HSEStartUpStatus = RCC_WaitForHSEStartUp();
  if(HSEStartUpStatus == SUCCESS)
  {
    RCC_HCLKConfig(RCC_SYSCLK_Div1);
    RCC_PCLK2Config(RCC_HCLK_Div1);
    RCC_PCLK1Config(RCC_HCLK_Div2);
    FLASH_SetLatency(FLASH_Latency_2);
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
    RCC_PLLCmd(ENABLE);
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    while(RCC_GetSYSCLKSource() != 0x08);
  }
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 | RCC_APB1Periph_USART2 | RCC_APB1Periph_USART3,ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO |  RCC_APB2Periph_USART1, ENABLE);
}

2、串口3GPIO配置,TRIGE为触发扫描引脚
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);        //禁止jtag 使能swd

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;                                          //MCU_TX3
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB,&GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;                                          //MCU_RX3
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB,&GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;                                                  //TRIGE
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA,&GPIO_InitStructure);
        GPIO_SetBits(GPIOA,GPIO_Pin_8);

3、USART3配置
USART_InitTypeDef USART_InitStructure;
       
        USART_InitStructure.USART_BaudRate = 9600;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

        USART_Init(USART3,&USART_InitStructure);
        USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
        USART_ClearFlag(USART3,USART_FLAG_TC);
        USART_Cmd(USART3, ENABLE);

4、NVIC配置
        NVIC_InitTypeDef NVIC_InitStructure;
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

        NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

5、USART3中断配置
/*
barcode
*/
void USART3_IRQHandler(void)
{
        if(USART_GetITStatus(USART3,USART_IT_RXNE) !=RESET)
        {
                receiv_scan_date(USART3);
                USART_ClearFlag(USART3,USART_IT_RXNE);
        }
}

6、相关函数:
void USART_PutString(USART_TypeDef* USARTx,char* ch)
{       
        while(*ch != '\0')
        {
                USART_ClearFlag(USARTx,USART_FLAG_TXE);
                 USART_SendData(USARTx,*ch);
                while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);
                ch++;
        }
}

void barcode_init(USART_TypeDef* USARTx)
{
        USART_PutString(USARTx,(char*)reset);
        delayms(20);
        USART_PutString(USARTx,(char*)add_suffix);
        delayms(20);
        memset((uint8_t *)scan_receiv,'\0',SCAN_RECEIV_SIZE*sizeof(uint8_t));
}
两条命令:
const uint8_t reset[]="$$$$#99900030;%%%%";
const uint8_t add_suffix[]="$$$$#99904111;#99904112;#99904114;%%%%";

在初始化的时候会调用barcode_init,然后会调用USART_PutString发送命令,每次第一次上电能够发送两条命令跑通整个程序,虽然也没有收到条形码扫描模块返回的数据,之后复位就会只发送第一条,然后进入了中断,出中断,进中断...诡异的是,我并没有开启发送中断,只开启了接收中断,所以进了中断后,也不执行if,然后退出进入退出进入...单步发现是在USART_PutString中while语句时进入的。

另外,条形码扫描模块的默认波特率为9600,所以串口3我也配置为9600.但是我发现改变波特率,如14400那么程序上电、复位都能跑通,只是在扫描到条形码后立刻卡死,也没有返回扫描到的条形码数据。

有没有同行遇见过类似的问题啊?大家交流交流啊
沙发
Ketose| | 2016-3-30 09:45 | 只看该作者
在中断处理里把
USART_ClearFlag(USART3,USART_IT_RXNE)
换成:
USART_ClearITPendingBit(USART3, USART_IT_RXNE);

使用特权

评论回复
板凳
羊斩熊|  楼主 | 2016-3-30 09:47 | 只看该作者
Ketose 发表于 2016-3-30 09:45
在中断处理里把
USART_ClearFlag(USART3,USART_IT_RXNE)
换成:

嗯嗯,谢谢回复,我试试

使用特权

评论回复
地板
羊斩熊|  楼主 | 2016-3-30 09:55 | 只看该作者
Ketose 发表于 2016-3-30 09:45
在中断处理里把
USART_ClearFlag(USART3,USART_IT_RXNE)
换成:

谢谢你,试过了,也不行。USART_ClearITPendingBit(USART3, USART_IT_RXNE);与USART_ClearFlag(USART3,USART_IT_RXNE);其实作用差不多吧,只是现在程序只会不停的进入中断,但是并没有进入if,所以不会执行到这个语句。我是这么想的,没有进入if,说明进入中断不是因为没有触发接收中断,应该是其它的什么原因。这个程序之前在另外一块板子上是可以正常运行的,那块单片机是stm32f103rct6

使用特权

评论回复
5
Ketose| | 2016-3-30 10:00 | 只看该作者
没有进入IF,说明中断源不是USART_IT_RXNE

使用特权

评论回复
6
Ketose| | 2016-3-30 10:03 | 只看该作者
另外:USART_ClearITPendingBit和USART_ClearFlag不一样。一定要用USART_ClearITPendingBit,不然会一直中断。

使用特权

评论回复
7
羊斩熊|  楼主 | 2016-3-30 10:04 | 只看该作者
Ketose 发表于 2016-3-30 10:00
没有进入IF,说明中断源不是USART_IT_RXNE

是的,我也纳闷,在USART_putstring这个函数里while语句进入的中断,可是我没有开发送中断

使用特权

评论回复
8
Ketose| | 2016-3-30 10:05 | 只看该作者
仿真看下,是什么中断。。。

使用特权

评论回复
9
羊斩熊|  楼主 | 2016-3-30 10:05 | 只看该作者
Ketose 发表于 2016-3-30 10:03
另外:USART_ClearITPendingBit和USART_ClearFlag不一样。一定要用USART_ClearITPendingBit,不然会一直中 ...

哦,谢谢提醒,学习了

使用特权

评论回复
10
羊斩熊|  楼主 | 2016-3-30 10:45 | 只看该作者
Ketose 发表于 2016-3-30 10:05
仿真看下,是什么中断。。。

用jlink的swd模式调试,发现是在USART_PutString函数中while语句时进的中断哦,搞不清楚中断源哦,查询一下发送标志位有没有置位也会进入中断,况且我还没开发送中断,想不通哦

使用特权

评论回复
11
Xflyan| | 2016-3-30 10:51 | 只看该作者
在中断内打个断点,停下来后看一下USART3寄存器的值具体是什么,看看有没有哪个地方设置错了

使用特权

评论回复
12
羊斩熊|  楼主 | 2016-3-30 11:17 | 只看该作者
Xflyan 发表于 2016-3-30 10:51
在中断内打个断点,停下来后看一下USART3寄存器的值具体是什么,看看有没有哪个地方设置错了 ...

谢谢回复,我试试

使用特权

评论回复
13
小了个明| | 2016-3-31 08:52 | 只看该作者
串口管脚加上拉电阻试试

使用特权

评论回复
14
huangqi412| | 2016-3-31 09:50 | 只看该作者
101跟103应该是兼容的吧,

另好奇101似乎很难见到,难道价格比103便宜?

使用特权

评论回复
15
xmshao| | 2016-3-31 10:43 | 只看该作者
receiv_scan_date(USART3);

==>里面写了些什么?

你中断不停进出的话怀疑某中断标志位没清,这里重点怀疑你的ORE位。

使用特权

评论回复
16
羊斩熊|  楼主 | 2016-3-31 15:23 | 只看该作者
小了个明 发表于 2016-3-31 08:52
串口管脚加上拉电阻试试

加不了了,板子都打回来了。下次记得加个增强抗干扰

使用特权

评论回复
17
羊斩熊|  楼主 | 2016-3-31 15:25 | 只看该作者
huangqi412 发表于 2016-3-31 09:50
101跟103应该是兼容的吧,

另好奇101似乎很难见到,难道价格比103便宜?

103贵几毛钱。。。兼容的,所以代码移植过来,只改了引脚定义神马的,函数什么的没什么变动

使用特权

评论回复
18
羊斩熊|  楼主 | 2016-3-31 15:29 | 只看该作者
xmshao 发表于 2016-3-31 10:43
receiv_scan_date(USART3);

==>里面写了些什么?

调用了USART_ReceiveData(USARTx)这个函数获取条形码的值,然后将这个值存入一个数组保存。溢出中断没开,也需要清标志位么?

使用特权

评论回复
19
xmshao| | 2016-3-31 17:23 | 只看该作者
羊斩熊 发表于 2016-3-31 15:29
调用了USART_ReceiveData(USARTx)这个函数获取条形码的值,然后将这个值存入一个数组保存。溢出中断没开 ...

如果先读了 SR, 然后又读了 DR的话 也就没事。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

12

帖子

0

粉丝