矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 2337|回复: 14

C51单片机串口编程求助

[复制链接]
     
发表于 2021-5-16 18:56:57 | 显示全部楼层 |阅读模式
本帖最后由 Fireflying 于 2021-5-16 19:02 编辑

学习串口通讯,自拟了一段程序如下,下载到单片机后不管用。

  1. /*********************************************************************************************
  2. 程序名:                STC12C4052AD单片机串口编程实验   
  3. 编写人:                Fireflying     
  4. 编写时间: 2021年05月16日
  5. 硬件支持: 采用STC12C4052AD(DIP20封装)
  6. 接口说明:    
  7. 修改日志:  
  8.   NO.1-                                                               
  9. /*********************************************************************************************
  10. 说明:串口初始化,固定波特率,通过STC-ISP向单片机发送设预设的数据,单片机接收到数据后点亮LED。
  11. /*********************************************************************************************/

  12. #include <STC12C2052AD.H> //STC12Cx052AD系列单片机头文件
  13. sbit PowerCtrl=P1^7;        //输出控制引脚:19脚
  14. unsigned char UART_data; //定义串口接收数据变量

  15. /*********************************************************************************************
  16. 函数名:UART串口初始化函数
  17. 调  用:UART_init();
  18. 参  数:无
  19. 返回值:无
  20. 结  果:启动UART串口接收中断,允许串口接收,启动T/C1产生波特率(占用)
  21. 备  注:振荡晶体为12MHz,初始化波特率9600
  22. /**********************************************************************************************/
  23. void UartInit(void)                //9600bps@12MHz
  24. {
  25.         EA = 1; //允许总中断
  26.         ES = 1; //允许UART串口
  27.         SCON = 0x50;                //8位数据,可变波特率
  28.         AUXR |= 0x40;                //定时器时钟1T模式
  29.         AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
  30.         TMOD &= 0x0F;                //设置定时器模式
  31.         TL1 = 0xC7;                //设置定时初始值
  32.         TH1 = 0xFE;                //设置定时初始值
  33.         TR1 = 1;                                //定时器1启动
  34. }

  35. /**********************************************************************************************/



  36. /*********************************************************************************************
  37. 函数名:主函数
  38. 调  用:无
  39. 参  数:无
  40. 返回值:无
  41. 结  果:程序开始处,无限循环
  42. 备  注:判断从串口接收到的数据,如果是“Turn on”就点亮LED,如果是“Turn off”就熄灭LED
  43. /**********************************************************************************************/
  44. void main (void)
  45. {
  46.         UartInit();
  47.         PowerCtrl=1;        //初始状态熄灭LED
  48.         while(1)
  49.         {
  50.                 if (RI == 1)        //接收中断标志位为1时
  51.                 {
  52.                         UART_data = SBUF;        //接收数据 SBUF 为单片机的接收缓冲寄存器
  53.                         RI = 0;                        //令接收中断标志位为0(软件清零)
  54.                         switch(UART_data)
  55.                         {
  56.                                 case 0x1a:PowerCtrl=0;break;//检测收到的数值为0x1a,就点亮LED
  57.                                 case 0x0f:PowerCtrl=1;break;//检测收到的数值为0x0f,就熄灭LED
  58.                         }

  59.                 }               

  60.         }
  61. }
  62. /**********************************************************************************************/

复制代码


把程序下载到单片机后,LED熄灭,用串口调试助手,向单片机发送0x1a,LED仍然是灭的,发送1a,还是灭的,改连续发送,LED还是灭的。

然后改程序,初始化先把LED点亮,用串口调试助手向单片机发送0x0f,LED仍然是亮的,发送0f,还是亮的,改连续发送,LED还是亮的。

换用另外一个串口调试助手,还是不管用。

是程序哪里有问题么?请各位老师指点一下,谢谢!
     
发表于 2021-5-16 19:37:01 | 显示全部楼层
在程序里对LED写1和0确认能正常控制LED;

如果有数码管之类的显示把收到的数据送显示看能不能正常接收;

如果没有,在程序里用串口发数据看能不能正常通信.
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2021-5-16 20:09:08 来自手机 | 显示全部楼层
diy1997 发表于 2021-5-16 19:37
在程序里对LED写1和0确认能正常控制LED;

如果有数码管之类的显示把收到的数据送显示看能不能正常接收;

程序里面修改LED初始状态是有效的。
没有数码管,只接了一枚LED。
您的意思是把串口接收缓冲区的数值用串口发回来,用串口助手读取?
回复 支持 反对

使用道具 举报

     
发表于 2021-5-16 20:25:38 | 显示全部楼层
Fireflying 发表于 2021-5-16 20:09
程序里面修改LED初始状态是有效的。
没有数码管,只接了一枚LED。
您的意思是把串口接收缓冲区的数值用 ...

随便发什么数据看看能不能正常通信.
回复 支持 反对

使用道具 举报

     
发表于 2021-5-16 21:03:35 来自手机 | 显示全部楼层
本帖最后由 快乐毛毛虫 于 2021-5-16 21:06 编辑

12M晶振,凭什么可以与计算机通信?要11.0592晶振的,你用传统的计数器来,不要1T,th0=0xfd
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2021-5-16 22:09:48 | 显示全部楼层
本帖最后由 Fireflying 于 2021-5-16 22:16 编辑
快乐毛毛虫 发表于 2021-5-16 21:03
12M晶振,凭什么可以与计算机通信?要11.0592晶振的,你用传统的计数器来,不要1T,th0=0xfd


您能否说具体一点?我那一段串口初始化程序,是从STC-ISP软件里面生成的。
我目前的理解,是只要单片机能设置到按照某个特定的波特率(本例是9600)通讯,电脑也设置成同样的波特率,应该就能通讯成功。
换一个角度,那么如果我手头的单片机STC12C4052AD本身是1T的单片机,使用外部12M晶振,这个条件无法使用串口跟电脑通讯?我觉得应该还是程序上存在问题吧?例如串口初始化参数不对之类。
另外,我的串口使用定时器1,为什么要设置TH0?
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2021-5-16 22:14:05 | 显示全部楼层
我现在学习串口通讯,眼前一个障碍,是很多例程里面对于“AUXR”寄存器,使用这样的赋值语句:
AUXR |= 0x40;
AUXR &= 0xFE;
这个甚么位与、位或,我搞不懂,也没有找到相应的说明教程,所以串口初始化设置搞得我很头疼。
回复 支持 反对

使用道具 举报

     
发表于 2021-5-17 12:15:04 | 显示全部楼层
Fireflying 发表于 2021-5-16 22:09
您能否说具体一点?我那一段串口初始化程序,是从STC-ISP软件里面生成的。
我目前的理解,是只要单片 ...

刚才用电脑看了你的程序,你用1T模式可以使用12M晶振.
错误在于你开了中断,但是你的程序没有按照串口中断来编写,而是查询RI,既然这样,你就应该ES=0,关闭中断.这样测试一下.
另外,串口调试助手除了串口端口参数要设置外,要按照HEX发送,不是ASCII发送.这样应该OK了.
4052CPU已经很老了,你要用15F,15W系列的学习.

评分

1

查看全部评分

回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2021-5-17 13:16:34 | 显示全部楼层
本帖最后由 Fireflying 于 2021-5-17 13:18 编辑
快乐毛毛虫 发表于 2021-5-17 12:15
刚才用电脑看了你的程序,你用1T模式可以使用12M晶振.
错误在于你开了中断,但是你的程序没有按照串口中断 ...


感谢!等我回家再试试。
另外请教一下,如果我没有调用中断只是查询RI的话,开启ES=1串口中断为什么不行?这之间的逻辑关系是怎样的?
串口助手确实是用HEX方式发送的。
回复 支持 反对

使用道具 举报

     
发表于 2021-5-17 15:11:13 | 显示全部楼层
Fireflying 发表于 2021-5-17 13:16
感谢!等我回家再试试。
另外请教一下,如果我没有调用中断只是查询RI的话,开启ES=1串口中断为什么不 ...

程序跳到中断入口了.去0023H地址了
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2021-5-17 15:58:11 | 显示全部楼层
快乐毛毛虫 发表于 2021-5-17 15:11
程序跳到中断入口了.去0023H地址了

是不是只要开启了中断,不管主程序里面是否调用,每当中断被触发,CPU都会跑去中断入口?
回复 支持 反对

使用道具 举报

     
发表于 2021-5-17 19:28:26 | 显示全部楼层
Fireflying 发表于 2021-5-17 15:58
是不是只要开启了中断,不管主程序里面是否调用,每当中断被触发,CPU都会跑去中断入口?

对,计算机与人一样。出了问题,就到固定的地方找处理问题的预案。然而,你没有,那就回不来了
回复 支持 反对

使用道具 举报

     
发表于 2021-8-8 10:18:48 | 显示全部楼层
查下全局中断是否打开了
回复 支持 反对

使用道具 举报

     
发表于 2021-8-8 19:45:59 | 显示全部楼层
AUXR |= 0x40;   ∥AUXR寄存器第五位置1
AUXR &= 0xFE;  ∥AUXR寄存器最后一位清零
回复 支持 反对

使用道具 举报

     
发表于 2021-8-8 20:42:29 | 显示全部楼层
中断处理函数呢?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2025-4-28 21:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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