找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6537|回复: 11
收起左侧

STC12C5A60S2单片机晶振22.1184,我想设置波特率115200,但接收的全部都是乱码

[复制链接]
ID:365486 发表于 2018-8-18 22:51 | 显示全部楼层 |阅读模式
我的MCU是STC12C5A60S2,晶振22.1184,我想设置波特率115200,但接收的全部都是乱码,9600的可以。麻烦大神帮忙解释一下。万分感谢!


代码如下
  1. #include"STC_NEW_8051.H"
  2. #include"ctype.h"
  3. #include"stdio.h"
  4. #include"string.h"
  5. #include"intrins.h"
  6. #include"delay.h"
  7. #include"EEPROM.h"
  8. #include"GPIO_explain.h"
  9. #include"GPIO_verdict.h"

  10. #define uchar unsigned char
  11. #define uint unsigned int
  12. #define ON 0
  13. #define OFF 1
  14. #define LOW 1
  15. #define HIGH 0
  16. unsigned int J;
  17. char xdata num[20];
  18. char xdata table[20];

  19. char xdata RX_date=0,RX_number=0;

  20. void init_time();

  21. void init_com();
  22. void init_num();

  23. void checkLED();

  24. void init_num()                 //数组初始化函数
  25. {
  26.     char i;
  27.     for(i=0; i<sizeof(num); i++)
  28.     {
  29.         num[ i]=0;[ i]
  30.     }
  31.     for(i=0; i<sizeof(table); i++)
  32.     {
  33.         table[ i]=0;[ i]
  34.     }
  35. }

  36. void init_com()                 //COM初始化
  37. {
  38. //    AUXR=AUXR|0x04;
  39. //    SCON=0x50;
  40. //    PCON=0x00;
  41. //    AUXR=AUXR|0x01;
  42. //    BRT=0xB8;         //波特率9600
  43. //    EA=1;
  44. //    ES=1;
  45. //    TI=0;
  46. //    RI=0;
  47. //    AUXR=AUXR|0x10;
  48. //


  49. //          TMOD=0x20;//0010 0000 设置计数器工作方式2
  50. //          SCON =0X50;//设置工作方式1  设定串行口工作方式,接收/发送控制以及设置状态标志
  51. //          PCON =0X80;//波特率加倍
  52. //          TH1=0XFF;
  53. //          TL1=0XFA;
  54. //          ES =1;
  55. //          EA=1;
  56. //          TR1=1;



  57. PCON |= 0x80; //使能波特率倍速位SMOD
  58. SCON = 0x50; //8位数据,可变波特率
  59. AUXR |= 0x40; //定时器1时钟为Fosc,即1T
  60. AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
  61. TMOD &= 0x0F; //清除定时器1模式位
  62. TMOD |= 0x20; //设定定时器1为8位自动重装方式
  63. TL1 = 0xF4; //设定定时初值
  64. TH1 = 0xF4; //设定定时器重装值
  65. ET1 = 0; //禁止定时器1中断
  66. TR1 = 1; //启动定时器1




  67. }
  68. void init_time()           //初始化定时器中断
  69. {
  70.     TMOD=0x21;
  71.     PS=1;
  72.     TH0=(-2000)/256;
  73.     TL0=(-2000)%256;
  74.     ET0=1;
  75.     TR0=1;
  76.     EA=1;
  77. }


  78. //void send_byte(char date)
  79. //{
  80. //    ES=0;
  81. //    REN=0;
  82. //    SBUF=date;
  83. //    while(!TI);
  84. //    TI=0;
  85. //    REN=1;
  86. //    ES=1;
  87. //}

  88. void send_date(char *P)        //发送数据
  89. {
  90.     ES = 0;
  91.     REN=0;
  92.     while(*P!='\0')
  93.     {
  94.         SBUF=*P;
  95.         P++;
  96.         while(!TI);          /*TI是串口发送完成标志,发送完成TI值为1
  97.                         while(!TI) 的意思就是等待串口发送完成(未完成TI值为0,
  98. (!TI)值为1,循环,直到串口发送完成,
  99. TI为1,(!TI)值为0,退出循环,向下执行)*/


  100.         TI=0;               //发送中断标志位,清0,取消此中断申请        //TI
  101.     }
  102.     REN=1;

  103.     ES = 1;
  104.     init_num();
  105. }

  106. void command_compare()        //命令判断函数
  107. {
  108.     int i,j;
  109.     if(RX_flage==1)
  110.     {
  111.         RX_flage=0;
  112.         for(i=0; i<sizeof(num); i++)
  113.         {
  114.             num[ i]= tolower(num[ i]);        //tolower是一种函数,功能是把字母字符转换成小写,非字母字符不做出处理。[ i][ i]
  115.         }
  116.         strncpy(table,num,strlen(num));
  117.         /*
  118.         strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,
  119.         中间某个位置,甚至是某个不确定的内存区域)开始扫描,
  120.         直到碰到第一个字符串结束符'\0'为止,然后返回计数器值(长度不包含'\0')。[1]
  121.         */
  122.         if(strncmp(table,"start",5)==0) { /*strncmp函数用于比较特定长度的字符串。返回值:当string1大于string2时,返回1;等于时,返回0;小于时,返回-1。*/
  123.             RX_date=0x01;
  124.          
  125.         }else if(strncmp(table,"stop",4)==0){
  126. RX_date=0x02;

  127. }
  128.         else
  129.         {
  130.             RX_date=0x00;        //send_date(table);send_date(num);send_date("\n\r");
  131.             send_date("ERROR command\r\n");
  132.             ES=1;
  133.             REN=1;
  134.             init_num();
  135.             return;
  136.         }

  137.         switch(RX_date)
  138.         {
  139.         case 0x01:
  140.             start_flage=1;
  141. open_LED=ON        ;
  142.             checkLED();
  143.             init_num();
  144.             break;
  145. case 0x02:
  146. open_LED=OFF;
  147. init_num();
  148. break;
  149.         default:
  150.             RX_date=0x00;
  151.             init_num();
  152.             send_date("ERROR command\r\n");
  153.             break;
  154.         }
  155.         RX_date=0x00;
  156.         RX_number=0;
  157.         init_num();
  158.     }
  159. }




  160. void main()
  161. {

  162.     P0=0xff;
  163.     P1=0xff;
  164.     P2=0xff;
  165.     P3=0xff;
  166.     P4SW=0x00;                 //设置P4口为普通IO口
  167.     P1M1=0x00;
  168.     P1M0=0xff;        //P1强推输出
  169.     P2M1=0x00;
  170.     P2M0=0xff;        //P2强推输出

  171.     init_time();   //初始化计时器中断
  172.     init_flage();  //初始化标志位
  173.     init_com();                 //初始化串口定义
  174.     init_num();        //清空串口中字符串
  175. send_date("\r\n Evan2018-01-07");  //在上电状态下,加这句输出语句,可以防止在接收的时候,第一个字符串匹配不上
  176.     while(1)
  177.     {
  178.         command_compare();
  179.     }
  180. }
  181. void time_0()interrupt 1 using 3
  182. {
  183.     unsigned int T;
  184.     TH0=(65535-2000)/256;
  185.     TL0=(65535-2000)%256;
  186.     T++;
  187. J++;
  188.     if(T==500)        {
  189.         T=0;
  190.         PCB_LED=!PCB_LED;
  191.     }
  192. }

  193. void RX_com() interrupt 4 using 0
  194. {
  195.     uchar temp;
  196.     char i;
  197.     if(RI)
  198.     {
  199.         temp=SBUF;
  200.         RI=0;
  201.         if(temp=='\n')         //换行'\n' 就是光标下移一行 却不会移到这一行的开头
  202.         {
  203.             return;
  204.         }
  205.         else
  206.         {
  207.             num[ i]=temp;[ i]
  208.             if(num[ i]=='\r')   //回车'\r'就是回到当前行的开头 却不会下移一行。  ‘\n\r’就是enter 回车的意思[ i]
  209.             {

  210.                 i=0;
  211.                 ES=0;
  212.                 REN=0;
  213.                 RX_flage=1;
  214.                 return;
  215.             }
  216.             i++;
  217.         }
  218.     }


  219. }
  220. void checkLED()
  221. {
  222.     if(K1==1)
  223.     {
  224.         send_date("\r\nRET1:FAIL END");
  225.     } else if(K1==0)
  226.     {
  227.         send_date("\r\nRET1:PASS END");
  228.     }



  229.     if(K2==1)
  230.     {
  231.         send_date("\r\nRET2:FAIL END");
  232.     } else if(K2==0)
  233.     {
  234.         send_date("\r\nRET2:PASS END");
  235.     }



  236.     if(K3==1)
  237.     {
  238.         send_date("\r\nRET3:FAIL END");
  239.     }        else if(K3==0)
  240.     {
  241.         send_date("\r\nRET3:PASS END");
  242.     }




  243.     if(K4==1)
  244.     {
  245.         send_date("\r\nRET4:FAIL END");
  246.     } else if(K4==0)
  247.     {
  248.         send_date("\r\nRET4:PASS END");
  249.     }

  250.     if(K5==1)
  251.     {
  252.         send_date("\r\nRET5:FAIL END");
  253.     } else if(K5==0)
  254.     {
  255.         send_date("\r\nRET5:PASS END");
  256.     }



  257.     if(K6==1)
  258.     {
  259.         send_date("\r\nRET6:FAIL END");
  260.     } else if(K6==0)
  261.     {
  262.         send_date("\r\nRET6:PASS END");
  263.     }
  264. }
复制代码



回复

使用道具 举报

ID:365486 发表于 2018-8-18 22:52 | 显示全部楼层
试过各种方法,9600的波特率接收和发送都没有问题。求大神帮助啊!万分感谢!
回复

使用道具 举报

ID:155507 发表于 2018-8-19 01:40 | 显示全部楼层
  1. void UartInit(void)                //115200bps@22.1184MHz
  2. {
  3.         SCON = 0x50;                //8位数据,可变波特率
  4.         AUXR |= 0x40;                //定时器1时钟为Fosc,即1T
  5.         AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
  6.         TMOD &= 0x0F;                //设定定时器1为16位自动重装方式
  7.         TL1 = 0xD0;                //设定定时初值
  8.         TH1 = 0xFF;                //设定定时初值
  9.         ET1 = 0;                //禁止定时器1中断
  10.         TR1 = 1;                //启动定时器1
  11. }




  12. void UartInit(void)                //115200bps@22.1184MHz
  13. {
  14.         SCON = 0x50;                //8位数据,可变波特率
  15.         AUXR &= 0xBF;                //定时器1时钟为Fosc/12,即12T
  16.         AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
  17.         TMOD &= 0x0F;                //设定定时器1为16位自动重装方式
  18.         TL1 = 0xFC;                //设定定时初值
  19.         TH1 = 0xFF;                //设定定时初值
  20.         ET1 = 0;                //禁止定时器1中断
  21.         TR1 = 1;                //启动定时器1
  22. }

复制代码

评分

参与人数 1黑币 +15 收起 理由
杨雪飞 + 15 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:365486 发表于 2018-8-19 11:50 | 显示全部楼层
回复

使用道具 举报

ID:96682 发表于 2018-8-19 13:27 | 显示全部楼层
evanboys 发表于 2018-8-18 22:52
试过各种方法,9600的波特率接收和发送都没有问题。求大神帮助啊!万分感谢!

因为这波特率与芯片还能匹配吧
回复

使用道具 举报

ID:365486 发表于 2018-8-20 01:16 | 显示全部楼层
wc86110 发表于 2018-8-19 13:27
因为这波特率与芯片还能匹配吧

您的意思是芯片问题,不是软件有问题对吗?
另外请教下,误差多大通讯会正常
回复

使用道具 举报

ID:388197 发表于 2018-8-20 17:11 | 显示全部楼层
有没有设置波特率加倍?
回复

使用道具 举报

ID:327030 发表于 2018-8-20 23:49 来自手机 | 显示全部楼层
你是不是用src-isp这个软件算的波特率,这好像算的不准我用它一次都没算对过
回复

使用道具 举报

ID:388354 发表于 2018-8-21 00:03 | 显示全部楼层
示波器抓波形看看
回复

使用道具 举报

ID:82586 发表于 2018-8-21 11:55 | 显示全部楼层
STC12C5A60S2,波特率做到115200没问题的;使用内部波特率发生器,不要使用定时器;
回复

使用道具 举报

ID:137736 发表于 2018-8-21 19:00 | 显示全部楼层
晶振准么,写个小程序,用一个端口输出方波,用频率计或示波器测一下。或者换11.059的晶体试试。
回复

使用道具 举报

ID:387076 发表于 2018-8-21 20:34 | 显示全部楼层
可以尝试将晶振换成11.0592MHz,看看能不能使用
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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