OpenEdv-开源电子网

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

原子哥和大神们:急救!!! STM32串口2 的收发问题 有图有真相 有源码

[复制链接]

7

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
91
金钱
91
注册时间
2011-12-9
在线时间
4 小时
发表于 2014-3-5 16:05:22 | 显示全部楼层 |阅读模式
原子哥和各路大神,请帮小弟看看串口UART2收发处理问题,我制定了一个协议格式,宗旨是将接收到的数据,确认无误后,再发送出去,出现下图的情况,为什么每次接受都只是前两个字节数据,而不是整个发送的数据,请大神们帮小弟看看,问题出在什么地方,附件里有源码,先谢谢了!



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

使用道具 举报

7

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
91
金钱
91
注册时间
2011-12-9
在线时间
4 小时
 楼主| 发表于 2014-3-5 16:17:54 | 显示全部楼层
回复【楼主位】kingbox568:
---------------------------------
源码压缩包传不上去,代码如下:

#include "usart2.h"
#include "led.h"
#include <stdarg.h>


static u8 Uart2ReceiveState;   // 表示接受中数据的状态
static u8 Uart2Rbuffer[30];    // 接受buffer

/***************************************************************************************************
 * 函数名:USART2_Config
 * 描述  :USART2 GPIO 配置,工作模式配置。9600 8-N-1
 * 输入  :无
 * 输出: 无
 * 调用  :外部调用
***************************************************************************************************/
void USART2_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

/* config USART2 clock */ //在使用外设时,不仅要使能其时钟,还要调用此函数使能外设才可以正常使用
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);    // APB2Periph
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 , ENABLE);    // APB1Periph   注意:USART2 是 APB1Periph 

/* USART2 GPIO config */
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;              //PA2 TX
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(GPIOA, &GPIO_InitStructure);                

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;              //PA3 RX
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //浮空输入
   GPIO_Init(GPIOA, &GPIO_InitStructure);  
  
/* USART2 mode config */
USART_InitStructure.USART_BaudRate = 9600;  // 波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b;  // 串口传输的字长:8位字长,也可以设置为9位
USART_InitStructure.USART_StopBits = USART_StopBits_1;  // 停止位设置为1位
USART_InitStructure.USART_Parity = USART_Parity_No ;  // 不设置奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;   // 不采用硬件流
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  // 配置双线全双工通讯,需要把Rx和Tx模式都开启
USART_Init(USART2, &USART_InitStructure);   //填充完结构体,调用库函数USART_Init()向寄存器写入配置参数

    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;         //抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          //IRQ通道使能
NVIC_Init(&NVIC_InitStructure);                                  //根据指定的参数初始化VIC寄存器
   
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);                   //开启中断

USART_Cmd(USART2, ENABLE);  //调用USART_Cmd() 使能USART外设

Uart2ReceiveState = ReceiveHead1;

}

/***************************************************************************************************
 * 函数名:USART2_IRQHandler
 * 描述  :USART2中断函数处理
 * 输入  :无
 * 输出  :无
***************************************************************************************************/
void USART2_IRQHandler(void)
{
u8 DataNum;   //  记录几个数据被接受
    u8 Data;

if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  
{
    USART_ClearITPendingBit(USART2,  USART_IT_RXNE);          //清除接收中断标志 

Data=USART_ReceiveData(USART2);

switch(Uart2ReceiveState)
     {
case ReceiveHead1: if(Data == 0x55)              
               {
                   Uart2Rbuffer[0] = Data;
                   Uart2ReceiveState = ReceiveHead2;
printf("\r\n Uart2Rbuffer[0] = %d \r\n", Data);
printf("\r\n Uart2ReceiveState = %d \r\n", Uart2ReceiveState);

               }
          break;

            case ReceiveHead2:  if(Data == 0xAA)
               {
                   Uart2Rbuffer[1] =   Data;
                   Uart2ReceiveState = ReceiveAddr;
printf("\r\n Uart2Rbuffer[1] = %d \r\n", Data);
printf("\r\n Uart2ReceiveState = %d \r\n", Uart2ReceiveState);
               }
               else
               {
                    Uart2ReceiveState = ReceiveHead1;
printf("\r\n Uart2ReceiveState = %d \r\n", Uart2ReceiveState);
               }
          break; 
            
            case ReceiveAddr:   if(Data == 0x10)
               {
                   Uart2Rbuffer[2] = Data;
                   Uart2ReceiveState = ReceiveDataLong;
printf("\r\n Uart2Rbuffer[2] = %d \r\n", Data);
printf("\r\n Uart2ReceiveState = %d \r\n", Uart2ReceiveState);
               }
               else
               {
                    Uart2ReceiveState = ReceiveHead1;
printf("\r\n Uart2Rbuffer[2] = %d \r\n", Data);
printf("\r\n Uart2ReceiveState = %d \r\n", Uart2ReceiveState);
               }
          break; 
      
            case ReceiveDataLong: if(Data < 0x20)
                 {
                        Uart2Rbuffer[3] = Data;
                     Uart2ReceiveState = ReceiveOrder;
  printf("\r\n Uart2Rbuffer[3] = %d \r\n", Data);
                 }
                 else
                 {
                     Uart2ReceiveState = ReceiveHead1;
  printf("\r\n Uart2Rbuffer[3]  = %d \r\n", 456 );
                 }
                                  break; 
            
            case ReceiveOrder:  Uart2Rbuffer[4] = Data;
               if(Uart2Rbuffer[3] == 0)
               {
                   Uart2ReceiveState = ReceiveTail; 
               }
               else
               {
                   Uart2ReceiveState = ReceiveData; 
                   DataNum = 0;
               }
          break;
                      
            case ReceiveData:   Uart2Rbuffer[5+DataNum] = Data;
                   DataNum++;
               if(Uart2Rbuffer[3] == DataNum)
               {
                  Uart2ReceiveState = ReceiveTail; 
               }
             break; 
            
            case ReceiveTail:   Uart2Rbuffer[5+Uart2Rbuffer[3]] = Data;
               Uart2ReceiveState = DisposeOrder; 
          break;        
            default:
                   Uart2ReceiveState = ReceiveHead1;
               DataNum = 0;
          break;
}

if(Uart2ReceiveState == DisposeOrder)
     {
USART_SendData(USART2, Uart2Rbuffer[20]);                  //将数据回送至超级终端
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);  //等待数据发送完毕


          
}
}


/***************************************************************************************************
 * 函数名:fputc
 * 描述  :重定向c库函数printf到USART2
 * 输入  :无
 * 输出  :无
 * 调用  :由printf调用
***************************************************************************************************/

int fputc(int ch, FILE *f)
{
USART_SendData(USART2, (unsigned char) ch);
while( USART_GetFlagStatus(USART2,USART_FLAG_TC)!= SET);
return (ch);
}
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2014-3-5 16:51:05 | 显示全部楼层
回复【2楼】kingbox568:
---------------------------------
思路没问题,但是方法问题多多。
USART2_IRQHandler,这个中断服务函数里面,你用这么多的printf...,怎么能处理的过来?
STM32接收数据,是接收一个字节就进入一次中断,你这printf,发送一次,可以接收好多个字节了,自然这些字节没法被你收到了。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

7

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
91
金钱
91
注册时间
2011-12-9
在线时间
4 小时
 楼主| 发表于 2014-3-6 09:19:25 | 显示全部楼层
回复【3楼】正点原子:

回复【2楼】kingbox568:
---------------------------------
思路没问题,但是方法问题多多。
USART2_IRQHandler,这个中断服务函数里面,你用这么多的printf...,怎么能处理的过来?
STM32接收数据,是接收一个字节就进入一次中断,你这printf,发送一次,可以接收好多个字节了,自然这些字节没法被你收到了。。。

---------------------------------
我用printf 函数,就是想看有没有接收到值,因为我把所有的printf 屏蔽掉,就没有任何数据返回,不知道有没有发送成功。
回复 支持 反对

使用道具 举报

70

主题

6761

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13117
金钱
13117
注册时间
2012-11-26
在线时间
3813 小时
发表于 2014-3-6 11:14:12 | 显示全部楼层
回复【4楼】kingbox568:

回复【3楼】正点原子:
回复【2楼】kingbox568:
---------------------------------
思路没问题,但是方法问题多多。
USART2_IRQHandler,这个中断服务函数里面,你用这么多的printf...,怎么能处理的过来?
STM32接收数据,是接收一个字节就进入一次中断,你这printf,发送一次,可以接收好多个字节了,自然这些字节没法被你收到了。。。

---------------------------------
我用printf 函数,就是想看有没有接收到值,因为我把所有的printf 屏蔽掉,就没有任何数据返回,不知道有没有发送成功。

---------------------------------
参考原子的程序  把所有的都接收下来,再printf试试吧
学无止境
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-8 15:52

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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