OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2598|回复: 8

求助一个搞了2天的奇葩问题,说起来很简单,实际上太奇葩

[复制链接]

1

主题

4

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2019-7-27
在线时间
2 小时
发表于 2019-7-27 10:49:58 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 花都拔得鸟 于 2019-7-27 10:58 编辑

整个事情是这样的。我有一个STM32F103zet6的板子,一个ESP8266的WIFI模块。一个USB转TTL的转接器。做了一个简单的实验。
步骤1:STM32F103zet6 的PA9,PA10->接USB转TTL的转接器的RXD和TXD,程序逻辑很简单,收到电脑发送给STM32板的一个数据,STM32板的LED0就闪一下。测试成功没有问题。说明程序是好的,STM32板也是好的。
步骤2:ESP8266的WIFI的RXD和TXD->接接USB转TTL的转接器的TXD和RXD,程序逻辑很简单,ESP8266使用AP模式TCP服务器,手机作为客户端连上以后发送数据,电脑显示手机发送过来的数据,测试成功没有问题。说明程序是好的,SP8266的WIFI模块也是好的。

问题来了:将ESP8266的WIFI的RXD和TXD接到STM32F103zet6 的PA9,PA10,同理,ESP8266使用AP模式TCP服务器,手机作为客户端连上以后发送数据,STM32板收到数据LED0就闪一下。不成功,其实也不是完全不成功。情况如下:

1、每次手机发送数据,平均发送20-30次,LED0闪一下。
2、偶尔出现某次主板重新加电后,程序正常,手机发一个数据,LED0闪一下。几率不到5%;
3、这两天的各种实验,已排除硬件自身原因,硬件没有问题的。

以下是关键代码:
  1. int main(void)
  2. {
  3.            vu8 key=0;        
  4.                 u8 Res;
  5.                 delay_init();
  6.                 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  7.                 uart_init(115200);         // 看了有些帖子,说波特率降低些,就试过,同时把STM32的板子和ESP8266都降低,无效。
  8.                 LED_Init();

  9.   while (1)
  10.   {
  11.     if(zj==1)
  12.                          {
  13.     LED0=0;
  14.     delay_ms(500);
  15.     zj=0;
  16.     LED0=1;
  17.                         }
  18.   }
  19. }         
复制代码
  1. #if EN_USART1_RX   //如果使能了接收
  2. //串口1中断服务程序
  3. //注意,读取USARTx->SR能避免莫名其妙的错误           
  4. u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
  5. //接收状态
  6. //bit15,        接收完成标志
  7. //bit14,        接收到0x0d
  8. //bit13~0,        接收到的有效字节数目
  9. u16 USART_RX_STA=0;       //接收状态标记         
  10. u8 zj=0;
  11.   
  12. void uart_init(u32 bound){
  13.   //GPIO端口设置
  14.   GPIO_InitTypeDef GPIO_InitStructure;
  15.         USART_InitTypeDef USART_InitStructure;
  16.         NVIC_InitTypeDef NVIC_InitStructure;
  17.          
  18.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);        //使能USART1,GPIOA时钟
  19.   USART_DeInit(USART1);  //复位串口1
  20.         //USART1_TX   GPIOA.9
  21.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  22.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  23.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
  24.   GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
  25.    
  26.   //USART1_RX          GPIOA.10初始化
  27.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  28.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  29.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  30.   GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  31.   //Usart1 NVIC 配置
  32.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  33.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
  34.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                //子优先级3
  35.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
  36.         NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器
  37.   
  38.    //USART 初始化设置

  39.         USART_InitStructure.USART_BaudRate = bound;//串口波特率
  40.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
  41.         USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  42.         USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
  43.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  44.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收发模式

  45.   USART_Init(USART1, &USART_InitStructure); //初始化串口1
  46.   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  47.   USART_Cmd(USART1, ENABLE);                    //使能串口1

  48. }


  49. void USART1_IRQHandler(void)                        //串口1中断服务程序
  50.         {
  51.         u8 Res;
  52. #if SYSTEM_SUPPORT_OS                 //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
  53.         OSIntEnter();   
  54. #endif
  55.         zj=1;//这里设置点灯,用ESP8266传入数据,这个中断偶尔进入一次,手机平均发送20-30次,LED0才闪一下。
  56.         if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
  57.                 {
  58.                 Res =USART_ReceiveData(USART1);        //读取接收到的数据

  59. //                zj=1;
  60. //                if(Res==0x31) zj=1;
  61. //                else zj=0;                        
  62.                
  63.                 if((USART_RX_STA&0x8000)==0)//接收未完成
  64.                         {
  65.                         if(USART_RX_STA&0x4000)//接收到了0x0d
  66.                                 {
  67.                                 if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
  68.                                 else USART_RX_STA|=0x8000;        //接收完成了
  69.                                 }
  70.                         else //还没收到0X0D
  71.                                 {        
  72.                                 if(Res==0x0d)USART_RX_STA|=0x4000;
  73.                                 else
  74.                                         {
  75.                                         USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
  76.                                         USART_RX_STA++;
  77.                                         if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收         
  78.                                         }                 
  79.                                 }
  80.                         }                    
  81.      }
  82. #if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
  83.         OSIntExit();                                                                                          
  84. #endif
  85. }
  86. #endif        
复制代码

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2019-7-27
在线时间
2 小时
 楼主| 发表于 2019-7-27 11:00:44 | 显示全部楼层
各位大神,帮帮忙,已处于快疯的边缘了。
回复

使用道具 举报

2

主题

84

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1096
金钱
1096
注册时间
2019-1-5
在线时间
257 小时
发表于 2019-7-27 14:00:05 | 显示全部楼层
你这里是UART中断都难得进入一次,那你确保手机客户端与esp8266连接上了吗,esp8266模块有两个电源,3.3v供电有可能会供电不足导致不停复位,先确定模块是不是正常工作;
如果按你说的硬件没问题,那么你单片机主动发送数据,看看手机能不能收到,查看UART程序到底有没有问题;
可以进行程序仿真,设置断点,细化步骤,一点点排查。
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2019-7-27
在线时间
2 小时
 楼主| 发表于 2019-7-27 16:26:14 | 显示全部楼层
又试了一天,找到根本问题了。
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入改为上拉。然后
  1.         if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  2.    {  
  3.                         USART_ClearITPendingBit(USART1,USART_IT_RXNE); //这里清除中断
复制代码


原因不了解。但是正常了。
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2019-7-27
在线时间
2 小时
 楼主| 发表于 2019-7-27 20:48:39 | 显示全部楼层
好奇怪,下午3点离开的时候是正常的。什么都没有动过,晚上上电,手机连接起发送数据,又不正常了。。。。
回复

使用道具 举报

6

主题

60

帖子

0

精华

初级会员

Rank: 2

积分
196
金钱
196
注册时间
2017-7-18
在线时间
31 小时
发表于 2019-7-29 16:08:53 | 显示全部楼层
建议串口接收数据使用DMA+空闲中断,不要每次接收到一个字节就进中断(而且还得判断结束标识),
一般来讲串口发送数据都是连续的,一帧数据完毕之后才会触发空闲中断,误触发很少(不敢说不存在),
回复

使用道具 举报

23

主题

86

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
299
金钱
299
注册时间
2019-7-20
在线时间
108 小时
发表于 2019-7-29 16:25:40 | 显示全部楼层
建议用定时器检测10MS判断串口是否接受完成,就是用定时器定时10MS,串口进入中断后,将这个定时器初值重新装载,这时候定时时间就不会超过10MS,但没有数据接受的时候,定时器中断就会触发,这时候置位一个接受标志位,让单片机及时的来出来这个接受数据,只有处理完成我们才将这个标志位置0,开始一轮数据的接受。
回复

使用道具 举报

9

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
195
金钱
195
注册时间
2015-12-30
在线时间
48 小时
发表于 2019-7-31 03:35:01 来自手机 | 显示全部楼层
串口接收程序有bug,连续接收会出错,你这是不是原子哥的程序改的,
回复

使用道具 举报

15

主题

866

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
7542
金钱
7542
注册时间
2016-11-30
在线时间
642 小时
发表于 2019-7-31 11:43:37 | 显示全部楼层
串口接受中断函数里边不要搞这么多事情。用一个缓存数组或者队列,把数据先接收回来,然后再main里去进行数据处理。
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-30 21:39

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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