野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 10688|回复: 5

串口收发+按键扫描程序跑死了

[复制链接]
发表于 2015-7-31 15:14:45 | 显示全部楼层 |阅读模式
本帖最后由 西点 于 2015-8-1 16:53 编辑

最近有个项目需要用到按键扫描,奋斗几天弄出来了,但是结果发现 这程序存在BUG。。。。
​程序开机时刻跑的很正常,一个小时左右却跑死了,主函数里面LED 灯不再闪烁,停在某一状态,复位后,程序又如开机一样可以跑了。
​很纠结,一个按键扫描程序居然跑死了,
​
​求高手指点指点,不甚感激。
​
​精简的源码如下:

#define USART1_REC_LEN   7​​
​#define Key_Press  1           //按键按下
#define Key_On     0           // 按键弹起
​
​volatile u16        g_u16_currentkey = 0;   
​volatile u8        Scankeystatus = 0;​         
u8  temp_key = 0;           ​
​u8 TxD_ToPC[8] = {0x71,0,0,0,0,0,0,0x71};        // 发送到上位机的信息
u8 USART1_RX_BUF[USART1_REC_LEN];     //
u8 USART1_RX_num = 0;
u8 RXD_FromPC[USART1_REC_LEN];         //

​// 按键扫描​
u8 Scan_key(void)
{
u8 key = 0;
​
  if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_0) == Key_Press)  key |= 0x01;
  if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1) == Key_Press)  key |= 0x02;
  if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2) == Key_Press)  key |= 0x04;
  if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3) == Key_Press)  key |= 0x08;

  return key;
}
​// 接收上位机的命令
​void ReceivedFromPC_order(void)
{
    u8 cmd;
    cmd = RXD_FromPC[0];
    switch(cmd)
   {
       case 0x71:
                      Scankeystatus = 1;         // 采集键盘状态标识    发送一次即可
                      break;
       case 0x72:
                     Scankeystatus = 0;
                     break;
   }​
​
​// 键盘状态重新打包发送
​void        Send_key_status(void)
{
    u8 sum,i;
​    TxD_ToPC[0] = 0x71;
    TxD_ToPC[1] = temp_key;
    TxD_ToPC[2] =        g_u16_currentkey;
    TxD_ToPC[3] =0x22;
    TxD_ToPC[4] = 0x55;  //   原来是采集别的数据,现在用固定的数代替
    TxD_ToPC[5] =0x66;
    TxD_ToPC[6] = 0xff;

    sum = 0;
   for(i = 0;i < 7; i++)
  {
      sum += TxD_ToPC;
   }
   TxD_ToPC[7] = sum;

   USART1_transmitS(TxD_ToPC,8);
}
&#8203;
&#8203;//串口1发送函数
&#8203;void USART1_transmit(unsigned char byte)
{
     USART_SendData(USART1,byte);                                
     while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}

void USART1_transmitS(unsigned char *dat,unsigned char num)
{
     unsigned char i;
     for(i=0;i<num;i++)
    {
         USART1_transmit(dat);
    }
}
// 串口1中断接收上位机函数&#8203;
&#8203;void USART1_IRQHandler(void)      
{
  u8 i;
  if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)
         {   
    USART1_RX_BUF[USART1_RX_num] = USART_ReceiveData(USART1);  //(USART1->DR)
   USART1_RX_num++;
   if(USART1_RX_num >= USART1_REC_LEN)
  {
      USART1_RX_num = 0;
      USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);         

            for(i = 0;i<7;i++)
             {
                  RXD_FromPC =  USART1_RX_BUF;
            }   
  ReceivedFromPC_order();

  USART_ITConfig( USART1,USART_IT_RXNE, ENABLE);   
   }
}
&#8203;}
&#8203;//  定时器3 /20ms / 发送开关状态给上位机
&#8203;void TIM3_IRQHandler(void)  
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);

if(Scankeystatus == 1)
{
  Send_key_status();
}
}
&#8203;
&#8203;// 主函数
&#8203;
&#8203;int main(void)
{

LED_GPIO_Config();   // LED2
delay_init();     
uart1_init(115200);
TIM3_Int_Init(200,7199);
&#8203; KEY_GPIO_Config();
  
temp_key = Scan_key();
g_u16_currentkey = temp_key;       // 第一次记录按键状态
&#8203;
delay_ms(100);
while(1)
{
   temp_key = Scan_key();            
   if(temp_key != g_u16_currentkey )   
   &#8203;{
        delay_ms(10);  
        temp_key = Scan_key();            
        if(temp_key != g_u16_currentkey )
        {
             g_u16_currentkey = Scan_key();           // 记录真实键值
        }
    }

  LED2 = 0;
delay_ms(180);
LED2 = 1;
delay_ms(180);
}
&#8203;}
&#8203;
串口、按键、LED、 定时器的初始化再次就不再啰嗦,基本是按照 例子改编的。
&#8203;
&#8203;困扰了好几天了,主程序老是跑死,定时器依然活着。  不知道哪里出了问题了。。。
&#8203;
&#8203;求高手破解。
&#8203;
回复

使用道具 举报

 楼主| 发表于 2015-7-31 15:18:10 | 显示全部楼层
够纠结的
回复

使用道具 举报

 楼主| 发表于 2015-7-31 19:27:06 | 显示全部楼层
难道单片机 串口不能连电脑太久通信嘛? 用串口助手 接收发送数据
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-7-31 19:35:54 | 显示全部楼层
u8 Scan_key(void)
{
u8 key = 0x5a;


//   if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_0) == Key_Press)  key |= 0x01;
//   if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1) == Key_Press)  key |= 0x02;
//   if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2) == Key_Press)  key |= 0x04;
//   if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3) == Key_Press)  key |= 0x08;
//           
  return key;
}

按键不再变化,但是 STM32在跑了2个小时后 依旧死机了。。。。
不懂,咋回事!!!

这个过程 ,串口一直在收发数据的
回复 支持 反对

使用道具 举报

发表于 2015-8-1 09:04:23 | 显示全部楼层
注意按键其中一个按下是高电平,一个按下是低电平,电平不对可能就卡在死循环检测状态了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-8-1 17:00:20 | 显示全部楼层
flyleaf 发表于 2015-8-1 09:04
注意按键其中一个按下是高电平,一个按下是低电平,电平不对可能就卡在死循环检测状态了

应该不会出现那种情况,我都接的一样的。

我想问下这串口这样写对不对:
void USART1_IRQHandler(void)      
{
  u8 i;
  if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)
        {   
    USART1_RX_BUF[USART1_RX_num] = USART_ReceiveData(USART1);  //(USART1->DR)
   USART1_RX_num++;
   if(USART1_RX_num >= USART1_REC_LEN)
  {
      USART1_RX_num = 0;
      USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);          

            for(i = 0;i<7;i++)
             {
                  RXD_FromPC =  USART1_RX_BUF;
            }   
  ReceivedFromPC_order();

  USART_ITConfig( USART1,USART_IT_RXNE, ENABLE);   
   }
}
}
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-9-22 23:39 , Processed in 0.038342 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表