打印
[STC单片机]

用STC11f04e中定时器0 及两个IO 口模拟串口 总是有问题

[复制链接]
3453|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhoujinming|  楼主 | 2014-7-28 22:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include"STC11.h"
#include"USART.h"

sbit TXB = P1^1; //RXD,单片机接收数据
sbit RXB = P1^0; //TXD,单片机发送数据

uchar TBUF,RBUF; //相当于串口中的SBUF

uchar TDAT;      //中间变量,TDAT负责将TBUF依次送到管脚上
uchar RDAT;                 //中间变量,RDAT将串口数据接收下来,送给RBUF

uchar TCNT,RCNT; //配合定时器,判断管脚状态
uchar TBIT,RBIT; //发送或接收时用来记录字节的位数

bit TING,RING;   //发送和接收的开始标志位
bit TEND,REND;         //类似于TI和RI,所以TEND的初始化值是1




void usart_init() //串口初始化
{
         
    AUXR |= 0x80;                //定时器时钟1T模式

//                                                                                                                                                                                                                                                                        TMOD &= 0xF0;                //设置定时器模式
        TMOD |= 0x01;                //设置定时器模式
         
        TH0=(BAUD>>8);
        TL0= BAUD;

                      
        TR0= 1;       
        PT0=1;
        ET0=1;                  
       


        TING=0;
        RING=0;
        TEND=1;
        REND=0;
        TCNT=0;
        RCNT=0;  
}
void RXD_DEAL()         //串口接收处理函数,相当于串口中断里面if(RI){;}的内容
{
        if(RING)
    {
            if(--RCNT==0)
            {
                         RCNT=3;
                         if(--RBIT==0)
                {
                                 RBUF=RDAT;
                                 RING=0;
                         REND=1;
                        }
                        else
                        {
                                 RDAT>>=1;
                                 if(RXB)
                                {
                                        RDAT|=0X80;
                                }
                        }
                }
        }
        else if(!RXB)
    {
                RING=1;
            RCNT=4;
            RBIT=9;
    }
}

void TXD_DEAL()         //串口接收处理函数,相当于串口中断里面if(TI){;}的内容
{
        if(--TCNT==0)
    {
                TCNT=3;
                if(TING)
                {
                    if(TBIT==0)
                           {
                        TXB=0;
                            TDAT=TBUF;
                             TBIT=9;
                }
                          else
                           {
                             TDAT>>=1;
                            if(--TBIT==0)
                             {
                                       TXB=1;
                                       TING=0;
                                       TEND=1;
                                 }
                                   else
                            {
                                    TXB=CY;
                            }
                          }
                }
          }
}


void put_char(uchar send_data)         //串口发送函数:单字节
{
        while(!TEND);
        TEND=0;
        TBUF=send_data;
        TING=1;
}

相关帖子

沙发
zhoujinming|  楼主 | 2014-7-28 22:59 | 只看该作者
这是是STC15系列的定时器0加IO口模拟串口 我移植过来的 怎么调试都不正确  就是用真实的串口发 模拟串口收  或用真实串口收  模拟串口发都不对 求指导

使用特权

评论回复
板凳
zhoujinming|  楼主 | 2014-7-28 23:01 | 只看该作者
求大神帮我指导下 这个有整个程序  希望大家给我指导下

STC11F04E模拟UART2.rar

44.58 KB

使用特权

评论回复
地板
ayb_ice| | 2014-7-29 07:56 | 只看该作者
牛人啊,中断都不用就搞定了

使用特权

评论回复
5
ningling_21| | 2014-7-29 07:56 | 只看该作者
zhoujinming 发表于 2014-7-28 22:59
这是是STC15系列的定时器0加IO口模拟串口 我移植过来的 怎么调试都不正确  就是用真实的串口发 模拟串口收  ...

真实串口收发都不对的话,肯定是程序的问题,注:这款芯片烧录时默认内部振荡器...

使用特权

评论回复
6
ayb_ice| | 2014-7-29 08:04 | 只看该作者
ningling_21 发表于 2014-7-29 07:56
真实串口收发都不对的话,肯定是程序的问题,注:这款芯片烧录时默认内部振荡器... ...

                        REND=0;
                        BUF[r++]=RBUF;
               
               
                       
                        SEND_UART(BUF[r]);

你这要发送的数据都还没有接收到嘛

使用特权

评论回复
7
ayb_ice| | 2014-7-29 08:08 | 只看该作者
你这什么模拟接收程序,都没有判断开始停止条件

使用特权

评论回复
8
zhoujinming|  楼主 | 2014-7-29 08:51 | 只看该作者
这个 是STC15系列的例程  其中模拟串口那一块我直接移植过来的

使用特权

评论回复
9
zhoujinming|  楼主 | 2014-7-29 08:52 | 只看该作者
ayb_ice 发表于 2014-7-29 07:56
牛人啊,中断都不用就搞定了

用到定时器0 中断的

使用特权

评论回复
10
zhoujinming|  楼主 | 2014-7-29 08:54 | 只看该作者
ayb_ice 发表于 2014-7-29 08:08
你这什么模拟接收程序,都没有判断开始停止条件

TXD_DEAL()  RXD_DEAL()  这个两个函数 其中有判断的

使用特权

评论回复
11
zhoujinming|  楼主 | 2014-7-29 08:56 | 只看该作者
ningling_21 发表于 2014-7-29 07:56
真实串口收发都不对的话,肯定是程序的问题,注:这款芯片烧录时默认内部振荡器... ...

你好 我使用的是外部晶振  晶振没有错

使用特权

评论回复
12
zhaoyu2005| | 2014-7-29 09:00 | 只看该作者
先测试发送,发送比接受好弄,定时往端口送数据就行了,接收的话就麻烦的,严格的得多次采样,这样就限制了最高速率,简单点就减少采样次数(印象中51是3次采样,你可以2次采样或者单次采样)。

使用特权

评论回复
13
ningling_21| | 2014-7-29 09:03 | 只看该作者
zhoujinming 发表于 2014-7-29 08:56
你好 我使用的是外部晶振  晶振没有错

先把硬件串口调试好,再调模拟的一步一步来吧...

使用特权

评论回复
14
ayb_ice| | 2014-7-29 09:06 | 只看该作者
zhoujinming 发表于 2014-7-29 08:54
TXD_DEAL()  RXD_DEAL()  这个两个函数 其中有判断的

我没有看出来

使用特权

评论回复
15
ayb_ice| | 2014-7-29 09:15 | 只看该作者
开始信号是用来同步的,我没有看出来你在哪里同步

使用特权

评论回复
16
zhoujinming|  楼主 | 2014-7-29 09:21 | 只看该作者
zhaoyu2005 发表于 2014-7-29 09:00
先测试发送,发送比接受好弄,定时往端口送数据就行了,接收的话就麻烦的,严格的得多次采样,这样就限制了 ...

嗯 是的  我也是采用三次的  我只用到19200   9600

使用特权

评论回复
17
ayb_ice| | 2014-7-29 09:26 | 只看该作者
zhoujinming 发表于 2014-7-29 09:21
嗯 是的  我也是采用三次的  我只用到19200   9600

采样三次也要同步的,否则可能造成数据移位的

使用特权

评论回复
18
coody| | 2014-7-29 10:53 | 只看该作者

/*------------------------------------------------------------------*/
/* --- STC MCU International Limited -------------------------------*/
/* --- STC 1T Series MCU Programme Demo ----------------------------*/
/* --- Fax: 86-755-82944243 ----------------------------------------*/
/* --- Tel: 86-755-82948412 ----------------------------------------*/
/* --- Web: www.**.com -----------------------------------------*/
/* If you want to use the program or the program referenced in the  */
/* article, please specify in which data and procedures from STC    */
/*------------------------------------------------------------------*/

/*      本程序经过测试完全正常, 不提供电话技术支持, 如不能理解, 请自行补充相关基础.  */


/*************        本程序功能说明        **************

                                测试说明

        本例程是使用STC系列MCU做的模拟串口。用户根据自己的时钟和波特率自行设置后编译下载。
       
        使用串口助手向MCU发送数据,MCU收到后原样返回给PC。
       
        本例程使用资源: Timer0中断.

*/

#include "reg51.h"

//#define MAIN_Fosc                 5529600L        //定义主时钟         600 ~ 4800
#define MAIN_Fosc                22118400L        //定义主时钟        2400 ~ 19200
//#define MAIN_Fosc                11059200L        //定义主时钟        1200 ~ 9600
//#define MAIN_Fosc                12000000L        //定义主时钟        1200 ~ 9600

#define BaudRate                9600                //模拟串口波特率

/***************************************************************************/

typedef bit BOOL;
typedef unsigned char         uchar;
typedef unsigned int         uint;

#define T0_Reload                (256 - MAIN_Fosc / 12 / BaudRate / 3)
#define D_RxBitLenth        9                //9: 8 + 1 stop
#define D_TxBitLenth        9                //9: 1 stop bit

sbit RXB = P3^0;                //define UART TX/RX port
sbit TXB = P3^1;

uchar  data TBUF,RBUF;
uchar  data TDAT,RDAT;
uchar  data TCNT,RCNT;        //发送和接收检测 计数器(3倍速率检测)
uchar  data TBIT,RBIT;        //发送和接收的数据计数器
uchar  data t, r;
uchar  data buf[16];

bit  TING,RING;        //正在发送或接收一个字节
bit  REND;                 //接收完的标志位

#define        RxBitLenth        9        //8个数据位+1个停止位
#define        TxBitLenth        9        //8个数据位+1个停止位

//-----------------------------------------
//UART模块的初始变量        initial UART module variable
void UART_INIT()
{
      TING = 0;
      RING = 0;
      REND = 0;
      TCNT = 0;
      RCNT = 0;
}

void main()
{
        TMOD |= 0x02;                                //timer0 work in 8-bit auto reload mode, 12T mode
        TL0 = T0_Reload;
        TH0 = T0_Reload;                //设置初始Timer0和重载值                initial timer0 and set reload value
        ET0 = 1;                                        //打开定时器0的中断                                enable timer0 interrupt
        TR0 = 1;                                        //启动tiemr0                                         tiemr0        start running
        PT0 = 1;                                        //设置定时器0的优先级为最高                improve timer0 interrupt priority
        EA = 1;                                                //打开总中断                                        open global interrupt switch

        UART_INIT();                                //UART模块的初始变量

        while (1)
        {
                if (REND)                                //如果接收完,把接收到的值存入接收buff
                {
                        REND = 0;
                        buf[r++ & 0x0f] = RBUF;
                }

                if(!TING)                //发送空闲
                {
                        if (t != r)        //有要发送的数据
                        {
                                TBUF = buf[t++ & 0x0f];
                                TING = 1;
                        }
                }
        }
}


//-----------------------------------------
//定时器0中断程序for UART 以波特率3倍的速度采样判断 开始位                Timer interrupt routine for UART
void tm0() interrupt 1
{

        if (RING)
        {
                if (--RCNT == 0)                                  //接收数据以定时器的1/3来接收
                {
                        RCNT = 3;                   //重置接收计数器  接收数据以定时器的1/3来接收        reset send baudrate counter
                        if (--RBIT == 0)                          //接收完一帧数据
                        {
                                RBUF = RDAT;            //存储数据到缓冲区        save the data to RBUF
                                RING = 0;               //停止接收                        stop receive
                                REND = 1;               //接收完成标志设置        set receive completed flag
                        }
                        else
                        {
                                RDAT >>= 1;                          //把接收的单b数据 暂存到 RDAT(接收缓冲)
                                if (RXB) RDAT |= 0x80;  //shift RX data to RX buffer
                        }
                }
        }

        else if (!RXB)                //判断是不是开始位 RXB=0;
        {
                RING = 1;       //如果是则设置开始接收标志位         set start receive flag
                RCNT = 4;       //初始化接收波特率计数器               initial receive baudrate counter
                RBIT = RxBitLenth;       //初始化接收的数据位数(8个数据位+1个停止位)    initial receive bit number (8 data bits + 1 stop bit)
        }

        if (TING)                        //发送开始标志位   judge whether sending
        {
                if (--TCNT == 0)                        //发送数据以定时器的1/3来发送
                {
                        TCNT = 3;                                //重置发送计数器   reset send baudrate counter
                        if (TBIT == 0)                        //发送计数器为0 表明单字节发送还没开始
                        {
                                TXB = 0;                        //发送开始位                                             send start bit
                                TDAT = TBUF;                //把缓冲的数据放到发送的buff                load data from TBUF to TDAT
                                TBIT = TxBitLenth;        //发送数据位数 (8数据位+1停止位)        initial send bit number (8 data bits + 1 stop bit)
                        }
                        else                                        //发送计数器为非0 正在发送数据
                        {
                                if (--TBIT == 0)        //发送计数器减为0 表明单字节发送结束
                                {
                                        TXB = 1;                //送停止位数据
                                        TING = 0;                //发送停止位                            stop send
                                }
                                else
                                {
                                        TDAT >>= 1;                //把最低位送到 CY(益处标志位) shift data to CY
                                        TXB = CY;                //发送单b数据                                write CY to TX port
                                }
                        }
                }
        }
}

使用特权

评论回复
评分
参与人数 2威望 +2 收起 理由
曹世鹏 + 1 赞一个!
zhoujinming + 1 赞一个!
19
zhoujinming|  楼主 | 2014-7-29 15:38 | 只看该作者
coody 发表于 2014-7-29 10:53
/*------------------------------------------------------------------*/
/* --- STC MCU International ...

看到问题在哪了  谢谢你

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

10

主题

46

帖子

0

粉丝