OpenEdv-开源电子网

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

串口如何判断接收的是什么数据?

[复制链接]

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
发表于 2016-7-11 10:09:39 | 显示全部楼层 |阅读模式
5金钱
我想用串口通信,如果从串口助手上发送00,就拉低GPIOA.1,如果串口助手上发送01  就拉高GPIOA.1;
如果串口助手上发送 10,就拉低GPIOC.1,如果串口助手上发送11  就拉高GOIOC.1。。
  我的程序如下,(估计是我的逻辑错误,完全不按照想法执行啊,,)
main.c 如下:
int main(void)
{

         GPIO_Init();
         delay_init();
         USART3_Init(9600);
         while(1)
         {
                 if(flag)
                 {
                         flag = 0;
                                if(buf[count = 0] == '1')
                      {
                              if(buf[count = 1] == '0')
                               {
                                       GPIO_ResetBits(GPIOC,GPIO_Pin_1);
             }
                              if(buf[count = 1] == '1')
                               {
                                       GPIO_SetBits(GPIOC,GPIO_Pin_1);
             }       
          }
       
                                        if(buf[count = 0] == '1')
                      {
                              if(buf[count = 1] == '0')
                               {
                                       GPIO_ResetBits(GPIOC,GPIO_Pin_1);
             }
                              if(buf[count = 1] == '1')
                               {
                                       GPIO_SetBits(GPIOC,GPIO_Pin_1);
             }       
          }
      }
          }
}

串口中断如下:
u8 i;
u8 buf[20];                        //存数用的数组
u8 count = 0;                //计一共发送和接收多少数据长度的
u8 flag = 0 ;
void USART3_IRQHandler(void)
{
        if(USART_GetITStatus(USART3,USART_IT_RXNE) != RESET)                  //如果进入中断了
        {       
                flag = 1;
                buf[count++] = USART_ReceiveData(USART3);                                                                //接数,存到buf里
               
                for(i = 0;i < count;i++)
                   {
                           USART_SendData(USART3,buf[i]);
       }
           count = 0;               
        }
                else
                        {
                                count = 0;                                        //没进中断的话,清一下count,清一下中断标志位。
                                USART_ClearITPendingBit(USART3,USART_IT_RXNE);
                        }
                       
}

GPIO.c 如下:
GPIO_InitTypeDef  GPIO_InitStructure;
       
        //RCC时钟使能 GPIOB.5  GPIOE.5
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);

        //GPIOA.1初始化
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       
        GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        //GPIOC.1初始化
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       
        GPIO_Init(GPIOC, &GPIO_InitStructure);
       
        GPIO_SetBits(GPIOA,GPIO_Pin_1);
        GPIO_SetBits(GPIOC,GPIO_Pin_1);




最佳答案

查看完整内容[请看2#楼]

这是我昨天自己鼓秋出来的最终版,只能发0123来控制GPIOA.1,GPIOC.1的高低电平。 有待参考。
越努力,越优秀;越独立,越自由
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-11 10:09:40 | 显示全部楼层
这是我昨天自己鼓秋出来的最终版,只能发0123来控制GPIOA.1,GPIOC.1的高低电平。 有待参考。

单主 多从 0123.rar

1.45 MB, 下载次数: 396

越努力,越优秀;越独立,越自由
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-11 10:18:25 | 显示全部楼层
发错了 main.c 是这样的:       
while(1)
         {
                 if(flag)
                 {
                         flag = 0;
                                if(buf[count = 0] == '0')
                      {
                              if(buf[count = 1] == '0')
                               {
                                       GPIO_ResetBits(GPIOA,GPIO_Pin_1);
             }
                              if(buf[count = 1] == '1')
                               {
                                       GPIO_SetBits(GPIOA,GPIO_Pin_1);
             }       
          }
       
                                        if(buf[count = 0] == '1')
                      {
                              if(buf[count = 1] == '0')
                               {
                                       GPIO_ResetBits(GPIOC,GPIO_Pin_1);
             }
                              if(buf[count = 1] == '1')
                               {
                                       GPIO_SetBits(GPIOC,GPIO_Pin_1);
             }       
          }
      }
          }
}
越努力,越优秀;越独立,越自由
回复

使用道具 举报

117

主题

598

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
1702
金钱
1702
注册时间
2012-5-10
在线时间
439 小时
发表于 2016-7-11 10:26:09 | 显示全部楼层
你发送是16进制还是发送的字符串,你这个程序应该发字符串,还有啊buf[count = 1]这个表达式取得是buf【0】的值么
如有技术问题,微信扫头像交流,STM32,JAVA,服务器
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-11 10:34:16 | 显示全部楼层
xsx127 发表于 2016-7-11 10:26
你发送是16进制还是发送的字符串,你这个程序应该发字符串,还有啊buf[count = 1]这个表达式取得是buf【0】 ...

对啊。buf[count = 0] 是判断串口助手发送的第一位是不是0
越努力,越优秀;越独立,越自由
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-11 10:36:41 | 显示全部楼层
我要实现的功能是这样的:
if(串口助手发送的第一位是0 并且 第二位是0)
{
拉低GPIOA.1;
}
if(串口助手发送的第一位是0 并且 第二位是1)
{
拉高GPIOA.1;
}
if(串口助手发送的第一位是1 并且 第二位是0)
{
拉低GPIOC.1;
}
if(串口助手发送的第一位是1 并且 第二位是1)
{
拉低GPIOC.1;
}


越努力,越优秀;越独立,越自由
回复

使用道具 举报

117

主题

598

帖子

1

精华

资深版主

Rank: 8Rank: 8

积分
1702
金钱
1702
注册时间
2012-5-10
在线时间
439 小时
发表于 2016-7-11 10:50:22 | 显示全部楼层
你这样做吧,还能省一个字节的内存,发送数据按照十六进制发送,00,01,10,11
[mw_shl_code=c,true]if(a == 0)
{
拉低GPIOA.1;
}
if(a == 1)
{
拉高GPIOA.1;
}
if(a == 2)
{
拉低GPIOC.1;
}
if(a == 3)
{
拉低GPIOC.1;
}[/mw_shl_code]
如有技术问题,微信扫头像交流,STM32,JAVA,服务器
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-11 11:02:49 | 显示全部楼层
xsx127 发表于 2016-7-11 10:50
你这样做吧,还能省一个字节的内存,发送数据按照十六进制发送,00,01,10,11
[mw_shl_code=c,true]if(a ...

不对啊。。
这样写可以实现 发送0 拉低GPIOA.1 发送1 拉高GPIOA.1
if(a == '0')
                      {
                                     GPIO_ResetBits(GPIOA,GPIO_Pin_1);
          }
                                        if(a == '1')
                      {
                                     GPIO_SetBits(GPIOA,GPIO_Pin_1);
          }       
而我现在想发送00,01来控制,  所以怎么判断从串口助手发送的数据时00还是01 呢?
越努力,越优秀;越独立,越自由
回复

使用道具 举报

1

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2016-3-19
在线时间
16 小时
发表于 2016-7-11 11:34:02 | 显示全部楼层
我认为这个是串口接收的问题,这样写只是两次接收一个字符,接收多个字符的话要使用结束符。
//                if(USART1->SR&(1<<5))
//                {
//                        data=USART1->DR;
//                        buff[count]=data;
//                        count++;
//                        if(buff[count-1]=='#')
//                        {
//                                buff[count]='\0';
//                                count=0;
//                                flag=1;
//                        }
//                        if(flag)
//                        {
//                                flag=0;
//                                USART1_printf(USART1,"你接收到的数据是:%s\n",buff);

//                                if(strcmp((const char *)buff,(const char *)"00")==0)
//                                {
//                                        Led_Control(1);
//                                        USART1_printf(USART1,"LED打开!\n");
//                                }
//                                else if(strcmp((const char *)buff,(const char *)"01")==0)
//                                {
//                                        Led_Control(0);
//                                        USART1_printf(USART1,"LED关闭!\n");
//                                }
//                                else
//                                {
//                                        USART1_printf(USART1,"输入错误\n");
//                                }
回复

使用道具 举报

5

主题

37

帖子

0

精华

初级会员

Rank: 2

积分
104
金钱
104
注册时间
2016-2-18
在线时间
13 小时
发表于 2016-7-11 11:36:42 | 显示全部楼层
楼上说的对!你的逻辑没有问题,问题是你发送的时候是通过串口调试助手发送的,如果是01,则为0x01,是一个8位的数,而你接收判断的时候却判断'1',这是字符1,ascii码一定不是数字0x01哦,虽然串口是按位发,但是发送和接收都是有缓存的,通常设置为8位,也就是一个字节,所以你在接收的时候最好打开接收中断,然后判断这一个字节的内容(STM32不像51单片机系统中有bit的定义),这样就可以了。
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-11 12:08:15 | 显示全部楼层
天涯歌戮 发表于 2016-7-11 11:36
楼上说的对!你的逻辑没有问题,问题是你发送的时候是通过串口调试助手发送的,如果是01,则为0x01,是一个 ...

如果我用串口助手发送00 那
if(buf[0]== ??)
                         {
                                  GPIO_ResetBits(GPIOA,GPIO_Pin_1);                                          
                         }
程序里应该写等于多少呢??
越努力,越优秀;越独立,越自由
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-11 12:21:35 | 显示全部楼层
八五三六 发表于 2016-7-11 11:34
我认为这个是串口接收的问题,这样写只是两次接收一个字符,接收多个字符的话要使用结束符。
//                if(USART ...

不对啊。。我是这样找你写的
[mw_shl_code=c,true]void USART3_IRQHandler(void)
{
        if(USART_GetITStatus(USART3,USART_IT_RXNE) != RESET)                  //如果进入中断了
        {       
                flag = 1;
                USART_ITConfig(USART3,USART_IT_RXNE,DISABLE);
                data = USART_ReceiveData(USART3);                                                                //接数,存到buf里
                buf[count] = data;
                count++;
               
                for(i = 0;i < count;i++)
                   {                
                           USART_SendData(USART3,buf);      
                   }

                if(strcmp((const char *)buf,(const char *)"00")==0)
                {
      GPIO_ResetBits(GPIOA,GPIO_Pin_1);
     }
         }
}[/mw_shl_code]
越努力,越优秀;越独立,越自由
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-11 12:36:59 | 显示全部楼层
八五三六 发表于 2016-7-11 11:34
我认为这个是串口接收的问题,这样写只是两次接收一个字符,接收多个字符的话要使用结束符。
//                if(USART ...

加完结束符是这样的
[mw_shl_code=c,true]void USART3_IRQHandler(void)
{
        if(USART_GetITStatus(USART3,USART_IT_RXNE) != RESET)                  //如果进入中断了
        {       
                flag = 1;
                USART_ITConfig(USART3,USART_IT_RXNE,DISABLE);
                data = USART_ReceiveData(USART3);                                                                //接数,存到buf里
                buf[count] = data;
                count++;
          if(buf[count-1]=='#')
       {
         buf[count]='\0';
         count=0;
         flag=1;
       }
                for(i = 0;i < count;i++)
                   {                
                           USART_SendData(USART3,buf);      
                   }
if(flag)
{
                if(strcmp((const char *)buf,(const char *)"00")==0)
                {
      GPIO_ResetBits(GPIOA,GPIO_Pin_1);
     }
         else if
                 (strcmp((const char *)buf,(const char *)"01")==0)
                {
      GPIO_SetBits(GPIOA,GPIO_Pin_1);
     }
         }
                 
}[/mw_shl_code]
越努力,越优秀;越独立,越自由
回复

使用道具 举报

10

主题

254

帖子

0

精华

高级会员

Rank: 4

积分
594
金钱
594
注册时间
2015-10-17
在线时间
145 小时
发表于 2016-7-11 12:42:36 | 显示全部楼层
这个问题,建议使用原子哥的USMART,直接发送函数比较方便,你自己写的话还要存到一个数组里面,然后再去解析,好多函数都需要自己写,利用USMART自己写一个带参数的函数就可以,简单实用。
开着单片机翱翔在天空
回复

使用道具 举报

1

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2016-3-19
在线时间
16 小时
发表于 2016-7-11 12:50:09 | 显示全部楼层
song15032 发表于 2016-7-11 12:36
加完结束符是这样的
[mw_shl_code=c,true]void USART3_IRQHandler(void)
{

第5行,应该是flag=0;比较对一点
第6行,我不是很明白这一句话有什么用
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-11 12:51:44 | 显示全部楼层
原_子_哥门徒 发表于 2016-7-11 12:42
这个问题,建议使用原子哥的USMART,直接发送函数比较方便,你自己写的话还要存到一个数组里面,然后再去解 ...

我要做的就是解析收到的这个数组里的数据啊。。。
  我想知道buf【count++】= USART_ReceiveData(USART3);         是把USART3的数据挨个放到
buf【】数组里了么,如果是,我怎么判断buf【0】是否是串口助手上发送的00?buf[1]是否是串口助手上发送的01呢?  
大神,求解啊。
越努力,越优秀;越独立,越自由
回复

使用道具 举报

1

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2016-3-19
在线时间
16 小时
发表于 2016-7-11 12:54:22 | 显示全部楼层
song15032 发表于 2016-7-11 12:36
加完结束符是这样的
[mw_shl_code=c,true]void USART3_IRQHandler(void)
{

16-19行的循环应该要放在21-22行中间,按我的理解,每发送一个字符都会触发一次串口中断,你发送“00”、“01”的话中断服务函数不止运行一次
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-11 12:55:54 | 显示全部楼层
八五三六 发表于 2016-7-11 12:50
第5行,应该是flag=0;比较对一点
第6行,我不是很明白这一句话有什么用

第五行,我前面中断函数外面 u8 flag = 0; 进中断,给标志位flag至1;
第六行,进入串口中断后,关闭中断,防止其他中断打断。 去掉也可以的。
加结束符 函数前面要写 [mw_shl_code=c,true]么?
如果加结束符成功了的话,串口助手要发送0#0 代表00 么?
越努力,越优秀;越独立,越自由
回复

使用道具 举报

1

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2016-3-19
在线时间
16 小时
发表于 2016-7-11 13:02:23 | 显示全部楼层
song15032 发表于 2016-7-11 12:55
第五行,我前面中断函数外面 u8 flag = 0; 进中断,给标志位flag至1;
第六行,进入串口中断后,关闭中 ...

flag是自己定义的一个标志,当flag==1的时候处理一些事情,处理完,要手动清零flag。
在我的程序里是当接收到#号才flag置1,解析接收到的字符串,而不是每接收一个字符就置1,如果你的程序第五行有flag=1的话,在串口调试助手上虽然你发送的字符都会回送,但字符串的判断程序就不能正常工作。
回复

使用道具 举报

5

主题

150

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2015-12-28
在线时间
132 小时
 楼主| 发表于 2016-7-11 13:08:16 | 显示全部楼层
八五三六 发表于 2016-7-11 13:02
flag是自己定义的一个标志,当flag==1的时候处理一些事情,处理完,要手动清零flag。
在我的程序里是当 ...

这个是我的工程,帮看看 修改一下呗,不胜感激!!

串口.rar

1.45 MB, 下载次数: 295

越努力,越优秀;越独立,越自由
回复

使用道具 举报

1

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2016-3-19
在线时间
16 小时
发表于 2016-7-11 13:23:48 | 显示全部楼层
你看看行不行

串口.rar

865.58 KB, 下载次数: 342

回复

使用道具 举报

6

主题

94

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1581
金钱
1581
注册时间
2016-7-2
在线时间
277 小时
发表于 2016-7-11 16:45:22 | 显示全部楼层
直接把data设置成外部变量不就可以了吗,在主函数中判断data,0x00拉低PA.1,0x01拉高PA.1,0x10拉低PC.1,0x11拉高PC.1
回复

使用道具 举报

5

主题

37

帖子

0

精华

初级会员

Rank: 2

积分
104
金钱
104
注册时间
2016-2-18
在线时间
13 小时
发表于 2016-7-12 08:39:19 | 显示全部楼层
song15032 发表于 2016-7-11 12:08
如果我用串口助手发送00 那
if(buf[0]== ??)
                         {

就是0,或者0x00
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-10 16:38

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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