搜索
bottom↓
回复: 12

【求助】看似简单的串口程序搞了一下午,请帮忙看看吧

[复制链接]

出5入4汤圆

发表于 2013-3-21 16:53:26 | 显示全部楼层 |阅读模式
本帖最后由 tim4146 于 2013-3-21 17:57 编辑

硬件连接:笔记本端是FT232,出来的TTL电平,将RXD,TXD交叉连接到单片机的TXD,RXD,杜邦线连的。晶振12M,调试助手设置的是9600的波特率,对应程序重装初值0XFD.
程序如下:

#include <reg51.h>
#include <intrins.h>
sbit P33=P3^3;
unsigned char tmp;
void send_char(unsigned char txd);

void delay20ms(void)   //误差 0us
{
    unsigned char a,b;
    for(b=215;b>0;b--)
        for(a=45;a>0;a--);
    _nop_();  //if Keil,require use intrins.h
    _nop_();  //if Keil,require use intrins.h
}
main()
{        unsigned char TEMP=0X00;  //临时
        TMOD = 0x20;                        // 定时器1工作于8位自动重载模式, 用于产生波特率
        TH1 = 0xFD;                                // 波特率4800
        TL1 = 0xFD;
       
        SCON = 0x50;                        // 设定串行口工作方式
        PCON &= 0xef;                        // 波特率不倍增
               
        TR1 = 1;                                // 启动定时器1
        IE = 0x00;                                // 禁止任何中断
        //P0=0X00;
        while(1)
        {
       
        if(RI)                                                // 是否有数据到来
                {
                        RI = 0;                                          //清零
                        tmp = SBUF;                                // 暂存接收到的数据
                send_char(tmp);                        // 回传接收到的数据
                }
       
       if(!P33)           //开发板上有个按钮,扫描按钮是否按下
                {
                 delay20ms();          //延时去抖动
                 while(!P33);         //松开时执行下一步
                 P0=~P0;                 //取反,使LED灯亮暗交替变换 这步能执行。
                 send_char(TEMP);  //发送一个0X00回去,发现收到的是乱码
                }
               
        }
}
void send_char(unsigned char txd)
// 传送一个字符
{
        SBUF = txd;
        while(!TI);                                // 等特数据传送
        TI = 0;                                        // 清除数据传送标志
}

实现目标:1、在串口调试助手中发送一个字节的字符,单片机收到之后将其发送回去让电脑的串口收到;
               2、检测一个按钮,在按钮松开时改变P0的电平达到LED亮暗交替的效果,并且随后给上位机发送0X00。

悲催的现实:调试助手发送一个字节之后发现单片机那边没反应;按钮按下松开之后LED灯正常切换状态,但是调试助手收到的一个字节的 内容是乱码(十六进制显示不是我预先设定的0x00)

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2013-3-21 17:50:59 | 显示全部楼层
楼主你没贴你单片机具体晶振是多少。。。

出5入4汤圆

 楼主| 发表于 2013-3-21 17:58:20 | 显示全部楼层
zjsxwc 发表于 2013-3-21 17:50
楼主你没贴你单片机具体晶振是多少。。。

晶振12M,调试助手设置的是9600的波特率,对应程序重装初值0XFD.
刚刚吃过晚饭,还的继续弄出来,本来是调试蓝牙模块的,发现串口直接相连都调不出来...哎

出0入0汤圆

发表于 2013-3-21 18:04:33 | 显示全部楼层
tim4146 发表于 2013-3-21 17:58
晶振12M,调试助手设置的是9600的波特率,对应程序重装初值0XFD.
刚刚吃过晚饭,还的继续弄出来,本来是 ...

12M晶振用9600Bps误差很大的,一般用4800Bps,保险点用更低的波特率试试
11.0592MHz的晶振的才能用9600Bps

出0入0汤圆

发表于 2013-3-21 18:12:24 | 显示全部楼层
12M晶振,9600的误差太大,根本无法通信

出5入4汤圆

 楼主| 发表于 2013-3-21 18:21:46 | 显示全部楼层
zjsxwc 发表于 2013-3-21 18:04
12M晶振用9600Bps误差很大的,一般用4800Bps,保险点用更低的波特率试试
11.0592MHz的晶振的才能用9600Bp ...

查表得知12M和11.0592M晶振相对9600波特率的初值都是FDH,所以直接换了晶振再试的,发现还是有问题,改成4800波特率下(TH1 = 0xF9;        TL1 = 0xF9;),还是乱了。兄台,你手上有开发板吗,直接烧进去帮我看看吧

出5入4汤圆

 楼主| 发表于 2013-3-21 18:32:14 | 显示全部楼层
binaimei2007 发表于 2013-3-21 18:12
12M晶振,9600的误差太大,根本无法通信

为了做纯粹的通信,也为了降低波特率,我采用1200波特率,定时器初值E6。
程序:
#include <reg51.h>
#include <intrins.h>
void send_char(unsigned char txd);
void delay500ms(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=23;c>0;c--)
        for(b=152;b>0;b--)
            for(a=70;a>0;a--);
}
main()
{        unsigned char TEMP=0XAA;  //临时
        TMOD = 0x20;                        // 定时器1工作于8位自动重载模式, 用于产生波特率
        TH1 = 0xe6;                                // 波特率1200
        TL1 = 0xe6;
        SCON = 0x50;                        // 设定串行口工作方式
        PCON &= 0xef;                        // 波特率不倍增       
        TR1 = 1;                                // 启动定时器1
        IE = 0x00;                                // 禁止任何中断
        while(1)
        {
                 delay500ms();
             send_char(TEMP);          //这步没效果,不懂               
        }
}
void send_char(unsigned char txd)
// 传送一个字符
{
        SBUF = txd;
        while(!TI);                                // 等特数据传送
        TI = 0;                                        // 清除数据传送标志
}

结果:
按理是500ms发送一次,实际收到的频率发现有丢失的现象,收到的内容不是预先设定的值...

出0入0汤圆

发表于 2013-3-21 18:55:53 | 显示全部楼层
//时钟22.1184M  
void        UartInit(void)
{
        AUXR1 |= 0;
        SCON = 0x52;    //
        TMOD|=0x20;
        TI=0;
        TH1=0xfd;        //19200bps       
//        TH1 =0xfa;        //9600bps
        TR1 = 1;
}

这是22.1184M用的一个初始化程序,11.0592M的话,波特率减半可以正常工作

出5入4汤圆

 楼主| 发表于 2013-3-21 19:01:03 | 显示全部楼层
wmm20031015 发表于 2013-3-21 18:55
//时钟22.1184M  
void        UartInit(void)
{

谢谢你,但是
AUXR1
是什么?

出0入0汤圆

发表于 2013-3-21 21:06:21 | 显示全部楼层
给你1个例子,自己看
  1. void HardInit(void)
  2. {
  3.         EA = 0;                                //关闭所有中断
  4.                   
  5.     /*定时器1,2模式设置*/
  6.     TMOD = (((unsigned char)0x02)<<1)|                //timer0工作方式选择,0-13位定时器/计数器工作模式,1-8位定时器/计数器工作模式
  7.                                                                                         //2-16位定时器/计数器工作模式,3-用作2个8位定时器/计数器工作模式
  8.                    (((unsigned char)0x00)<<2)|                 //timer0,0-定时器,1-计数器
  9.                    (((unsigned char)0x00)<<3)|                //timer0,1-T/C启动受双重信号的控制,0-T/C启动仅受TRx位控制
  10.                    (((unsigned char)0x01)<<5)|                   //timer1工作方式选择,0-13位定时器/计数器工作模式,1-8位定时器/计数器工作模式
  11.                                                                                         //2-16位定时器/计数器工作模式,
  12.                    (((unsigned char)0x00)<<6)|                   //timwer1,0-定时器,1-计数器
  13.                    (((unsigned char)0x00)<<7);                //timwer1,1-T/C启动受双重信号的控制,0-T/C启动仅受TRx位控制

  14.         /*定时器0设置*/
  15.         TH0 = 0xf7;
  16.     TL0 = 0x85;

  17.         /*定时器1设置*/
  18.         //作为波特率发生器
  19.         //SMOD = 0;                //不加倍
  20.         TL1 = 0xFD;     //11.0592MHz 0xFDH-9600 */
  21.         TH1 = 0xFD;       

  22.         /*定时器2设置*/
  23.         T2CON = 0x00;        //自动重装,16位

  24.     RCAP2H = 0xBC;    //50ms中断一次
  25.     RCAP2L = 0x00;
  26.     TH2 = 0xBC;
  27.     TL2 = 0x00;

  28.     /*串口设置*/
  29.     SCON = 0x50;
  30.     PCON &= 0x7F;

  31.     /*外部中断0,1设置*/
  32.     //IT0 = 1;                //跳变触发
  33.     //IT1 = 1;          //跳变触发

  34.         /*中断优先级设置*/
  35.         PX0 = 0;                //外部中断0的优先级位
  36.         PT0 = 0;                //定时器0优先级位
  37.         PX1 = 0;                //外部中断1的优先级位
  38.         PT1 = 0;                //定时器1的优先级位
  39.         PS = 0;                        //串口中断的优先级位
  40.         PT2 = 0;                //定时器2的优先级位

  41.     /*中断使能设置*/
  42.     EX0 = 0;              //外部中断允许位
  43.     ET0 = 1;              //定时器0中断允许位
  44.     EX1 = 0;              //外部中断1允许位
  45.     ET1 = 0;              //定时器1中断允许位
  46.     ES = 1;               //串行通讯中断允许位
  47.     ET2 = 1;              //定时器2中断允许位

  48.     EA = 1;        //开总中断
  49.     TR0 = 0;      //定时器0启动
  50.     TR1 = 1;      //定时器1启动
  51.     TR2 = 1;      //定时器2不启动
  52. }
复制代码
注意:使用了中断,晶振11.0592

出5入4汤圆

 楼主| 发表于 2013-3-21 21:30:51 | 显示全部楼层
感谢各位的帮助,我最后调试出来了。软件本身应该是没有问题的,硬件出现了问题。

出0入0汤圆

发表于 2013-3-21 21:41:40 | 显示全部楼层
tim4146 发表于 2013-3-21 19:01
谢谢你,但是
AUXR1
是什么?

新唐的51里的一个寄存器,其他51注释掉就行了

出0入0汤圆

发表于 2013-3-21 21:48:31 | 显示全部楼层
你直接就把手体电脑串口和单片机接在一起了???
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-23 09:33

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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