精华内容
下载资源
问答
  • 51单片机模拟串口

    2011-10-10 09:23:48
    51单片机模拟9600波特率的串口收发
  • 51单片机模拟串口的三种方法
  • 51单片机模拟串口通信,含电路仿真图.
  • 单片机模拟串口通信(查询方式和中断方式两种_均源码_带原理图)
  • 本资源是51单片机模拟串口通信头文件,内含详细的使用说明。只需几个步骤即可移植到你的51程序中。在51单片机内置的串口收发模块不够用时,使用本头文件可模拟出一个半双工的串口。
  • 单片机串口学习资料,是一个非常有用的好资料!
  • 51单片机模拟串口的三种方法【转】

    千次阅读 2008-05-11 00:11:00
    随着单片机的使用日益频繁,用其作前置机进行采集和通信也常见于各种应用,一般是利用前置机采集各种终端数据后进行处理、存储,再主动或...本文所说的模拟串口, 就是利用51的两个输入输出引脚如P1.0和P1.1,置1或

    随着单片机的使用日益频繁,用其作前置机进行采集和通信也常见于各种应用,一般是利用前置

    机采集各种终端数据后进行处理、存储,再主动或被动上报给管理站。这种情况下下,采集会需

    要一个串口,上报又需要另一个串口,这就要求单片机具有双串口的功能,但我们知道一般的51

    系列只提供一个串口,那么另一个串口只能靠程序模拟。

    本文所说的模拟串口, 就是利用51的两个输入输出引脚如P1.0和P1.1,置1或0分别代表高低电

    平,也就是串口通信中所说的位,如起始位用低电平,则将其置0,停止位为高电平,则将其置

    1,各种数据位和校验位则根据情况置1或置0。至于串口通信的波特率,说到底只是每位电平持续

    的时间,波特率越高,持续的时间越短。如波特率为9600BPS,即每一位传送时间为

    1000ms/9600=0.104ms,即位与位之间的延时为为0.104毫秒。单片机的延时是通过执行若干条

    指令来达到目的的,因为每条指令为1-3个指令周期,可即是通过若干个指令周期来进行延时的,

    单片机常用11.0592M的的晶振,现在我要告诉你这个奇怪数字的来历。用此频率则每个指令周期

    的时间为(12/11.0592)us,那么波特率为9600BPS每位要间融多少个指令周期呢?

    指令周期s=(1000000/9600)/(12/11.0592)=96,刚好为一整数,如果为4800BPS则为

    96x2=192,如为19200BPS则为48,别的波特率就不算了,都刚好为整数个指令周期,妙吧。至于

    别的晶振频率大家自已去算吧。

    现在就以11.0592M的晶振为例,谈谈三种模拟串口的方法。

    方法一:延时法

        通过上述计算大家知道,串口的每位需延时0.104秒,中间可执行96个指令周期。

    #define uchar unsigned char

    sbit P1_0 = 0x90;

    sbit P1_1 = 0x91;

    sbit P1_2 = 0x92;

    #define RXD P1_0

    #define TXD P1_1

    #define WRDYN 44 //写延时

    #define RDDYN 43 //读延时

    //往串口写一个字节

    void WByte(uchar input)

    {

        uchar i=8;

        TXD=(bit)0;                     //发送启始

        Delay2cp(39);

        //发送8位数据位

        while(i--)

        {

            TXD=(bit)(input&0x01);     //先传低位

            Delay2cp(36);

            input=input>>1;

        }

        //发送校验位(无)

        TXD=(bit)1;                     //发送结束

        Delay2cp(46);

    }

    //从串口读一个字节

    uchar RByte(void)

    {

        uchar Output=0;

        uchar i=8;

        uchar temp=RDDYN;

        //发送8位数据位

    Delay2cp(RDDYN*1.5);         //此处注意,等过起始位

        while(i--)

        {

            Output >>=1;

            if(RXD) Output  |=0x80;     //先收低位

            Delay2cp(35);             //(96-26)/2,循环共

    占用26个指令周期

        }

        while(--temp)                    //在指定的

    时间内搜寻结束位。

        {

            Delay2cp(1);

            if(RXD)break;             //收到结束位便退出

        }

        return Output;

    }

    //延时程序*

    void Delay2cp(unsigned char i)

    {

        while(--i);                     //刚好两个

    指令周期。

    }

        此种方法在接收上存在一定的难度,主要是采样定位存在需较准确,另外还必须知道

    每条语句的指令周期数。此法可能模拟若干个串口,实际中采用它的人也很多,但如果你用Keil 

    C,本人不建议使用此种方法,上述程序在P89C52、AT89C52、W78E52三种单片机上实验通过。

    方法二:计数法

        51的计数器在每指令周期加1,直到溢出,同时硬件置溢出标志位。这样我们就可以

    通过预置初值的方法让机器每96个指令周期产生一次溢出,程序不断的查询溢出标志来决定是否

    发送或接收下一位。

        

    //计数器初始化

    void S2INI(void)

    {

        TMOD |=0x02;                //计数器0,方式2

    TH0=0xA0;                    //预值为256-96=140,十六进制A0

        TL0=TH0;        

        TR0=1;                        //开始计数

        TF0=0;

    }

    void WByte(uchar input)

    {

        //发送启始位

        uchar i=8;

        TR0=1;

        TXD=(bit)0;

        WaitTF0();

        //发送8位数据位

        while(i--)

        {

            TXD=(bit)(input&0x01);     //先传低位

            WaitTF0();

            input=input>>1;

        }

        //发送校验位(无)

        //发送结束位

        TXD=(bit)1;

        WaitTF0();

        TR0=0;

    }    

    //查询计数器溢出标志位

    void WaitTF0( void )

    {

        while(!TF0);

        TF0=0;

    }

        接收的程序,可以参考下一种方法,不再写出。这种办法个人感觉不错,接收和发送

    都很准确,另外不需要计算每条语句的指令周期数。

    方法三:中断法

        中断的方法和计数器的方法差不多,只是当计算器溢出时便产生一次中断,用户可以

    在中断程序中置标志,程序不断的查询该标志来决定是否发送或接收下一位,当然程序中需对中

    断进行初始化,同时编写中断程序。本程序使用Timer0中断。

    #define TM0_FLAG P1_2 //设传输标志位

    //计数器及中断初始化

    void S2INI(void)

    {

        TMOD |=0x02;                //计数器0,方式2

        TH0=0xA0;                    //预值为256-96=140,十六进制A0

        TL0=TH0;        

        TR0=0;                         //在发送或

    接收才开始使用

        TF0=0; 

        ET0=1;                         //允许定时器0中断

        EA=1;                         //中断允许

    总开关

    }

    //接收一个字符

    uchar RByte()

    {

        uchar Output=0;

        uchar i=8;

        TR0=1;                         //启动Timer0

        TL0=TH0;

        WaitTF0();                    //等过起始

        //发送8位数据位

        while(i--)

        {

            Output >>=1;

            if(RXD) Output  |=0x80;     //先收低位

            WaitTF0();                //位间延时

        }

        while(!TM0_FLAG) if(RXD) break;

        TR0=0;                         //停止

        Timer0

        return Output;

    }

    //中断1处理程序

    void IntTimer0() interrupt 1

    {

        TM0_FLAG=1;                //设置标志位。

    }

    //查询传输标志位

    void WaitTF0( void )

    {

    while(!TM0_FLAG); 

    TM0_FLAG=0;                 //清标志位

    }

        中断法也是我推荐的方法,和计数法大同小异。发送程序参考计数法,相信是件很容

    易的事。

    另外还需注明的是本文所说的串口就是通常的三线制异步通信串口(UART),只用RXD、TXD、

    GND

    展开全文
  • 附:51 IO口模拟串口通讯C源程序(定时器计数法)#i nclude sbit BT_SND =P1^0;sbit BT_REC =P1^1;/**//**********************************************IO 口模拟232通讯程序使用两种方式的C程序 占用...
    附:51 IO口模拟串口通讯C源程序(定时器计数法)
    #i nclude 
    sbit BT_SND 
    =P1^0;
    sbit BT_REC 
    =P1^1;
    /**********************************************

    IO 口模拟232通讯程序

    使用两种方式的C程序 占用定时器0

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


    #define MODE_QUICK

    #define F_TM F0

    #define TIMER0_ENABLE  TL0=TH0; TR0=1;
    #define TIMER0_DISABLE TR0=0;

    sbit ACC0
    =   ACC^0;
    sbit ACC1
    =   ACC^1;
    sbit ACC2
    =   ACC^2;
    sbit ACC3
    =   ACC^3;
    sbit ACC4
    =   ACC^4;
    sbit ACC5
    =   ACC^5;
    sbit ACC6
    =   ACC^6;
    sbit ACC7
    =   ACC^7;

    void IntTimer0() interrupt 1
    {
    F_TM
    =1;
    }

    //发送一个字符
    void PSendChar(unsigned char inch)
    {
    #ifdef MODE_QUICK
    ACC
    =inch;

    F_TM
    =0;
    BT_SND
    =0//start bit
    TIMER0_ENABLE; //启动
    while(!F_TM);

    BT_SND
    =ACC0; //先送出低位
    F_TM=0;
    while(!F_TM);

    BT_SND
    =ACC1;
    F_TM
    =0;
    while(!F_TM);

    BT_SND
    =ACC2;
    F_TM
    =0;
    while(!F_TM);

    BT_SND
    =ACC3;
    F_TM
    =0;
    while(!F_TM);

    BT_SND
    =ACC4;
    F_TM
    =0;
    while(!F_TM);

    BT_SND
    =ACC5;
    F_TM
    =0;
    while(!F_TM);

    BT_SND
    =ACC6;
    F_TM
    =0;
    while(!F_TM);

    BT_SND
    =ACC7;
    F_TM
    =0;
    while(!F_TM);

    BT_SND
    =1;
    F_TM
    =0;
    while(!F_TM);


    TIMER0_DISABLE; 
    //停止timer
    #else
    unsigned 
    char ii;

    ii
    =0;

    F_TM
    =0;
    BT_SND
    =0//start bit
    TIMER0_ENABLE; //启动
    while(!F_TM);

    while(ii<8)
    {
    if(inch&1)
    {
    BT_SND
    =1;
    }

    else
    {
    BT_SND
    =0;
    }

    F_TM
    =0;
    while(!F_TM);
    ii
    ++;
    inch
    >>=1;
    }

    BT_SND
    =1;
    F_TM
    =0;
    while(!F_TM);

    #endif
    TIMER0_DISABLE; 
    //停止timer
    }

    //接收一个字符
    unsigned char PGetChar()
    {
    #ifdef MODE_QUICK

    TIMER0_ENABLE;
    F_TM
    =0;
    while(!F_TM); //等过起始位
    ACC0=BT_REC;

    TL0
    =TH0;

    F_TM
    =0;
    while(!F_TM);
    ACC1
    =BT_REC;

    F_TM
    =0;
    while(!F_TM);
    ACC2
    =BT_REC;

    F_TM
    =0;
    while(!F_TM);
    ACC3
    =BT_REC;

    F_TM
    =0;
    while(!F_TM);
    ACC4
    =BT_REC;

    F_TM
    =0;
    while(!F_TM);
    ACC5
    =BT_REC;

    F_TM
    =0;
    while(!F_TM);
    ACC6
    =BT_REC;

    F_TM
    =0;
    while(!F_TM);
    ACC7
    =BT_REC;

    F_TM
    =0;

    while(!F_TM)
    {
    if(BT_REC)
    {
    break;
    }

    }

    TIMER0_DISABLE; 
    //停止timer
    return ACC;
    #else
    unsigned 
    char rch,ii;
    TIMER0_ENABLE;
    F_TM
    =0;
    ii
    =0;
    rch
    =0;
    while(!F_TM); //等过起始位

    while(ii<8)
    {
    rch
    >>=1;
    if(BT_REC)
    {
    rch
    |=0x80;
    }

    ii
    ++;
    F_TM
    =0;
    while(!F_TM);

    }

    F_TM
    =0;
    while(!F_TM)
    {
    if(BT_REC)
    {
    break;
    }


    }

    TIMER0_DISABLE; 
    //停止timer
    return rch;

    #endif

    }

    //检查是不是有起始位
    bit StartBitOn()
    {
    return  (BT_REC==0);

    }

    void main()
    {
    unsigned 
    char gch;

    TMOD
    =0x22/*定时器1为工作模式2(8位自动重装),0为模式2(8位
    自动重装) 
    */

    PCON
    =00;

    TR0
    =0//在发送或接收才开始使用
    TF0=0;
    TH0
    =(256-96); //9600bps 就是 1000000/9600=104.167微秒 执行的
    timer是
    //             
    104.167*11.0592/12= 96
    TL0
    =TH0;
    ET0
    =1;
    EA
    =1;

    PSendChar(
    0x55);
    PSendChar(
    0xaa);
    PSendChar(
    0x00);
    PSendChar(
    0xff);

    while(1)
    {
    if(StartBitOn())
    {
    gch
    =PGetChar();
    PSendChar(gch);
    }

    }
    展开全文
  • 51单片机系列单片机三种方法模拟串口的程序方法
  • 单片机模拟了一个串口,使用P2.1作为发送端 把单片机中存放的数据通过P2.1作为串口TXD发送出去
  • 51单片机串口程序

    2014-04-11 14:19:33
    51单片机串口程序,模拟两路单片机串口通讯。
  • 用汇编语言编写的51单片机串口和模拟串口收发多个数据程序。单片机自带串口作为串口1,与上位机通讯。用外部中断模拟串口作为串口2,与现场仪表通讯。从单片机初始化到各个单元子程序均有。方便开发者使用。改程序...
  • 下面给大家介绍一下51单片机IO口模拟串口通讯C源程序。
  • 51的计数器在每指令周期加1,直到溢出,同时硬件置溢出标志位。这样我们就可以通过预置初值的方法让机器每96个指令周期产生一次溢出,程序不断的查询溢出标志来决定是否发送或接收下一位。
  • 本压缩包是用C语言编写,同时利单片机仿真软件,进行仿真
  • 延时法分 析: 此种方法在接收上存在一定的难度,主要是采样定位需较准确,另外还必须知道每条语句的指令周期数。
  • 中断的方法和计数器的方法差不多,只是当计算器溢出时便产生一次中断,用户可以在中断程序中置标志,程序不断的查询该标志来决定是否发送或接收下一位,当然程序中需对中断进行初始化,同时编写中断程序。...
  • 51单片机IO口模拟串口通讯1-延时法

    千次阅读 2013-03-05 09:43:10
    相关内容主要参考了网上《51单片机模拟串口的三种方法》和《单片机IO口模拟串口程序(发送+接收)》两篇文档,并动手做了一下实验。感受颇多。  硬件环境:STC89C52  软件环境:IDE Keil uVision V4.10  ...

      最近因工作需要,研究了一下单片机IO口模拟串口通讯的相关知识。相关内容主要参考了网上《51单片机模拟串口的三种方法》和《单片机IO口模拟串口程序(发送+接收)》两篇文档,并动手做了一下实验。感受颇多。

        硬件环境:STC89C52

        软件环境:IDE Keil uVision V4.10

                            编译器 C51 V9.0

        代码如下:

     

    1. /********************************************** 
    2. 方法1:延时法 
    3. 硬件:11.0592MHz晶振,STC89C52,RXD P1.0 TXD P1.1 
    4. 波特率:9600 
    5. 描述:所谓延时法是指根据模拟出的波特率,每1位持续的时间的长短是通过循环空指令来延时的。 
    6.  
    7. 测试1:上电发送1个0x01的字符 
    8. 测试2:上电后等待接收,接收到PC发送的0x01字符后,将此字符+1后再发送 
    9.  
    10. 结果: 
    11. 测试1:正确!接收到1个0x01的字符 
    12. 测试2-1:正确!分别一个一个发送0x01,0x02,0x03,0x04,0x05,均正常接收 
    13. 测试2-2: 错误!一起发送0x01,0x02,0x03,0x04,0x05,丢包,只能接收0x02,0x04,0x06 
    14.  
    15. 时间:2012.07.25 于单位 
    16. **********************************************/  
    17. #include "reg52.h"  
    18. #define uchar unsigned char  
    19.   
    20. sbit P1_0 = 0x90;  
    21. sbit P1_1 = 0x91;  
    22. sbit P1_2 = 0x92;  
    23.   
    24. #define RXD P1_0  
    25. #define TXD P1_1  
    26. #define WRDYN 44                    //写延时  
    27. #define RDDYN 43                    //读延时  
    28.   
    29. void Delay2cp(unsigned char i);  
    30.   
    31. //往串口写一个字节  
    32. void WByte(uchar input)  
    33. {  
    34.     uchar i=8;  
    35.     TXD=(bit)0;                     //发送启始位  
    36.     Delay2cp(39);  
    37.   
    38.     //发送8位数据位  
    39.     while(i--)  
    40.     {  
    41.         TXD=(bit)(input&0x01);      //先传低位  
    42.         Delay2cp(36);  
    43.         input=input>>1;  
    44.     }  
    45.   
    46.     //发送校验位(无)  
    47.     TXD=(bit)1;                     //发送结束位  
    48.     Delay2cp(46);  
    49. }  
    50.   
    51. //从串口读一个字节  
    52. uchar RByte(void)  
    53. {  
    54.     uchar Output=0;  
    55.     uchar i=8;  
    56.     uchar temp=RDDYN;  
    57.   
    58.     //发送8位数据位  
    59.     Delay2cp(RDDYN*1.5);            //此处注意,等过起始位  
    60.     while(i--)  
    61.     {  
    62.         Output >>=1;  
    63.         if(RXD) Output   |=0x80;    //先收低位  
    64.         Delay2cp(35);               //(96-26)/2,循环共占用26个指令周  
    65.     }  
    66.   
    67.     while(--temp)                   //在指定的时间内搜寻结束位。  
    68.     {  
    69.         Delay2cp(1);  
    70.         if(RXD)break;               //收到结束位便退  
    71.     }  
    72.   
    73.     return Output;  
    74. }  
    75.   
    76. //延时程序*  
    77. void Delay2cp(unsigned char i)  
    78. {  
    79.      while(--i);                    //刚好两个指令周期。  
    80. }  
    81.   
    82. void main()  
    83. {   uchar ccc;  
    84.   
    85.     //测试1     
    86.     //WByte(0x01);  
    87.     //while(1){;}   
    88.   
    89.     //测试2     
    90.     while(1)  
    91.     {  
    92.         if(RXD==0)  
    93.         {  
    94.             ccc=RByte();  
    95.             WByte(ccc+1);  
    96.         }  
    97.     }  
    98. }  

    附几张抓到的波形:

    测试1:十六进制字符0x01的波形


     测试1:发送出来的字符

    测试2:依次发送0x01,0x02,0x03,0x04,0x05接收到的字符

    测试2:一起发送0x01,0x02,0x03,0x04,0x05字符

     

     

    结论:发送和接收字符均正常,没加缓冲,大数据量未测试。

    展开全文
  • 模拟串口就是利用51的两个输入输出引脚如P1.0和P1.1,置1或0分别代表高低电平,也就是串口通信中所说的位,如起始位用低电平,则将其置0,停止位为高电平,则将其置1,各种数据位和校验位则根据情况置1或置0。
  • 51单片机普通的IO口模拟串口通信, 本实验需要两张stc8a8k实验板,连接方法: 实验板1的P1.0连接实验板2的P1.1; 实验板1的P1.1连接实验板2的P1.0; 如需改变波特率,请改动延时函数,具体延时时间请参考串口通信...
  • 单片机IO模拟串口,以51单片机为例说明,新学习的可以看看,很实用的文档
  • 通过串口发送接收数据(串口工作方式1) 实现思路: 定时器设置 串口设置 工作方式 波特率 开启定时/计数器 串口执行 接收数据 发送数据 - - - - - - -...

    ————————————————————————————————————————————

    实验7.4:RS232串口应用实例

    设计要求:

    通过串口发送接收数据(串口工作方式1)

    实现思路:

    • 定时器设置
    • 串口设置
      • 工作方式
      • 波特率
    • 开启定时/计数器
    • 串口执行
      • 接收数据
      • 发送数据

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    实现代码:

     1 #include <reg51.h>
     2 main()
     3 {
     4     TMOD = 0x20;
     5     SM0 = 0;
     6     SM1 = 1;
     7     REN = 1;
     8     PCON = 0;
     9     TH1 = 0xFD; //253=256-(1*11.0592*10^6)/(384*9600)
    10     TL1 = 0xFD;
    11     TR1 = 1;
    12     P1 = SBUF;
    13     while(!RI);
    14     RI = 0;
    15     SBUF = P1;
    16     while(!TI);
    17     TI = 0;
    18 }

     

    ————————————————————————————————————————————

    实验7.5:MAX487多机通信应用实例

    设计要求:

    在主从3个单片机中进行双机通信,当从机显示的数字和主机相同,则表示该主机和从机正在通信。按下主机按键切换当前对象。

    实现思路:

    • 主机端

      在主机中设置定时器和串口参数,并一直保持发送数据的状态。

      通过MAX487芯片将3个单片机连接,并通过设置/RE、DE管脚控制单片机输入输出状态。

      需要按下主机按键时检测按键状态,切换当前对象,设置中断,并标记此时状态是从机1或从机2。

      //中断发生时按照中断优先级,主机先执行cort++并发送信息,主机中断结束后才进入从机中断。

      如果是从机1,输出状态下发送对应数字,输入状态下设置单片机通信(非多机通信)接收并显示对应数字,重置输出状态。从机2同理。

    • 从机端

      设置与主机相同的串口参数和定时器和默认显示值。允许接收中断

      当按键被按下,判断主机要通信的是否是自己,是则显示对应数字并向主机发送数字,否则重置状态。

    执行流程:(多机通信模式)

    • 主机

    • 从机

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    实现代码:SM2=1,多机通信模式!

    • 主机
       1 #include <reg51.h>
       2 #include <intrins.h>
       3 unsigned char cort = 0;
       4 sbit P3_5 = P3 ^ 5;
       5 key_serial() interrupt 0 using 1
       6 {
       7     ++cort;
       8     if (cort == 3)
       9         cort = 1;
      10 }
      11 void main()
      12 {
      13     P2 = 0xff;
      14     TMOD = 0x20;
      15     TH1 = 0xFD;
      16     TL1 = 0xFD;
      17     PCON = 0x00;
      18     TR1 = 1;
      19     SCON = 0xF8;
      20     EA = 1;
      21     EX0 = 1;
      22     IT0 = 1;
      23     P3_5 = 1;
      24     while(1)
      25     {
      26         if (cort == 1)
      27         {
      28             SBUF = 0x01;
      29             while(TI != 1);
      30             TI = 0;
      31             P3_5 = 0;
      32             RB8 = 1;
      33             while(RI != 1);
      34             RI = 0;
      35             P2 = SBUF;
      36             P3_5 = 1;
      37         }
      38         if(cort == 2)
      39         {
      40             SBUF = 0x02;
      41             while(TI != 1);
      42             TI = 0;
      43             P3_5 = 0;
      44             RB8 = 1;
      45             while(RI != 1);
      46             RI = 0;
      47             P2 = SBUF;
      48             SM2 = 1;
      49             P3_5 = 1;
      50         }
      51 
      52     }
      53 }
    • 从机1
       1 #include <reg51.h>
       2 #include <intrins.h>
       3 sbit P3_5 = P3 ^ 5;
       4 void serial(void) interrupt 4 using 1
       5 {
       6     ES = 0;
       7     RI = 0;
       8     if (SBUF == 0x01)
       9     {
      10         P3_5 = 1;
      11         RI = 0;
      12         TB8 = 1;
      13         P1 = 0x10;
      14         SBUF = 0x10;
      15         while(!TI);
      16         TI = 0;
      17     }
      18     else P1 = 0;
      19     P3_5 = 0;
      20     ES = 1;
      21 }
      22 void main()
      23 {
      24     P1 = 0x00;
      25     TMOD = 0x20;
      26     TH1 = 0xFD;
      27     TL1 = 0xFD;
      28     PCON = 0x00;
      29     TR1 = 1;
      30     SCON = 0xF0;
      31     EA = 1;
      32     ES = 1;
      33     P3_5 = 0;
      34     while(1)
      35         _nop_();
      36 }
    • 从机2
       1 #include <reg51.h>
       2 #include <intrins.h>
       3 sbit P3_5 = P3 ^ 5;
       4 void serial() interrupt 4 using 1
       5 {
       6     ES = 0;
       7     RI = 0;
       8     if (SBUF == 0x02)
       9     {
      10         P3_5 = 1;
      11         RI = 0;
      12         TB8 = 1;
      13         P1 = 0x20;
      14         SBUF = 0x20;
      15         while(!TI);
      16         TI = 0;
      17     }
      18     else P1 = 0;
      19     P3_5 = 0;
      20     ES = 1;
      21 }
      22 void main()
      23 {
      24     P1 = 0x00;
      25     TMOD = 0x20;
      26     TH1 = 0xFD;
      27     TL1 = 0xFD;
      28     PCON = 0x00;
      29     TR1 = 1;
      30     SCON = 0xF0;
      31     EA = 1;
      32     ES = 1;
      33     P3_5 = 0;
      34     while(1)
      35         _nop_();
      36 }

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    实现代码:SM2=0,单机通信模式!

    • 主机
       1 #include <reg52.h>
       2 unsigned char cort = 0;
       3 sbit P3_5 = P3 ^ 5;
       4 void key_serial() interrupt 0 using 1
       5 {
       6     ++cort;
       7 }
       8 void main()
       9 {
      10     P2 = 0x0f;
      11     TMOD = 0x20;
      12     TH1 = 0xFD;
      13     TL1 = 0xFD;
      14     PCON = 0x00;
      15     TR1 = 1;
      16     SCON = 0xD0;
      17     EA = 1;
      18     EX0 = 1;
      19     IT0 = 1;
      20     P3_5 = 1;
      21     while(1)
      22     {
      23         if (cort == 1)
      24         {
      25             SBUF = 0x01;
      26             while(!TI);
      27             TI = 0;
      28             P3_5 = 0;
      29             while(!RI);
      30             RI = 0;
      31             P2 = SBUF;
      32             P3_5 = 1;
      33         }
      34         if(cort == 2)
      35         {
      36             SBUF = 0x02;
      37             while(!TI);
      38             TI = 0;
      39             P3_5 = 0;
      40             while(!RI);
      41             RI = 0;
      42             P2 = SBUF;
      43             P3_5 = 1;
      44         }
      45         if (cort == 3)
      46             cort = 1;
      47     }
      48 }
    • 从机1
       1 #include <reg51.h>
       2 #include <intrins.h>
       3 sbit P3_5 = P3 ^ 5;
       4 void serial(void) interrupt 4 using 1
       5 {
       6     ES = 0;
       7     RI = 0;
       8     P2 =  SBUF;
       9     if (SBUF == 0x01)
      10     {
      11         P3_5 = 1;
      12         P1 = 0x10;
      13         SBUF = 0x30;
      14         while(!TI);
      15         TI = 0;
      16     }
      17     else P1 = 0;
      18     P3_5 = 0;
      19     ES = 1;
      20 }
      21 void main()
      22 {
      23     P1 = 0x00;
      24     TMOD = 0x20;
      25     TH1 = 0xFD;
      26     TL1 = 0xFD;
      27     PCON = 0x00;
      28     TR1 = 1;
      29     SCON = 0xD0;
      30     EA = 1;
      31     ES = 1;
      32     P3_5 = 0;
      33     while(1)
      34         _nop_();
      35 }
    • 从机2:略

    ————————————————————————————————————————————

    关于该实验在多机通信和单机通信下不同情况的讨论

    • 在单机通信模式下,SM2 == 0

      初始化:SCON = D0

      发送完毕:TI=0

      接收完毕:RI=0

      中断触发条件:RI=0SM2=0RI置位

      此情况下,发送和接收信息结束后需要对RITI手动置为0即可。

    • 在多机通信模式下,SM201之间调整

      初始化:主机:SCON = F8;从机:SCON = F0

      中断触发条件:接收到的第九位RB9==1RI置位(如果RB8=0RI就会等于0,就不能进入接收中断,自然丢失信息了。)

         

    • 51单片机原理及应用(陈海宴)书P129案例是在主机发送状态下使用多机通信,接收状态下使用单机通信,在理解上容易出现错误,过程分析及代码如下:

      实现代码:

      • 主机:
         1 #include <reg51.h>
         2 #include <intrins.h>
         3 unsigned char cort = 0;
         4 sbit P3_5 = P3 ^ 5;
         5 key_serial() interrupt 0 using 1
         6 {
         7     ++cort;
         8 }
         9 void main()
        10 {
        11     P2 = 0xff;
        12     TMOD = 0x20;
        13     TH1 = 0xFD;
        14     TL1 = 0xFD;
        15     PCON = 0x00;
        16     TR1 = 1;
        17     SCON = 0xF8;
        18     EA = 1;
        19     EX0 = 1;
        20     IT0 = 1;
        21     P3_5 = 1;
        22     while(1)
        23     {
        24         if (cort == 1)
        25         {
        26             SBUF = 0x01;
        27             while(TI != 1);
        28             TI = 0;
        29             P3_5 = 0;
        30             SM2 = 0;
        31             while(RI != 1);
        32             RI = 0;
        33             P2 = SBUF;
        34             SM2 = 1;
        35             P3_5 = 1;
        36         }
        37         if(cort == 2)
        38         {
        39             SBUF = 0x02;
        40             while(TI != 1);
        41             TI = 0;
        42             P3_5 = 0;
        43             SM2 = 0;
        44             while(RI != 1);
        45             RI = 0;
        46             P2 = SBUF;
        47             SM2 = 1;
        48             P3_5 = 1;
        49         }
        50         if (cort == 3)
        51             cort = 1;
        52         SM2 = 1;
        53     }
        54 }
      • 从机1
         1 #include <reg51.h>
         2 #include <intrins.h>
         3 sbit P3_5 = P3 ^ 5;
         4 void serial(void) interrupt 4 using 1
         5 {
         6     ES = 0;
         7     RI = 0;
         8     if (SBUF == 0x01)
         9     {
        10         P3_5 = 1;
        11         SM2 = 0;
        12         P1 = 0x10;
        13         SBUF = 0x10;
        14         while(!TI);
        15         TI = 0;
        16     }
        17     else P1 = 0;
        18     SM2 = 1;
        19     P3_5 = 0;
        20     ES = 1;
        21 }
        22 void main()
        23 {
        24     P1 = 0x00;
        25     TMOD = 0x20;
        26     TH1 = 0xFD;
        27     TL1 = 0xFD;
        28     PCON = 0x00;
        29     TR1 = 1;
        30     SCON = 0xF0;
        31     EA = 1;
        32     ES = 1;
        33     P3_5 = 0;
        34     while(1)
        35         _nop_();
        36 }
      • 从机2:略

    转载于:https://www.cnblogs.com/hughdong/p/6861735.html

    展开全文
  • 相关内容主要参考了网上《51单片机模拟串口的三种方法》和《单片机IO口模拟串口程序(发送+接收)》两篇文档,并动手做了一下实验。感受颇多。  硬件环境:STC89C52  软件环境:IDE Keil uVision V4.10  编译器 ...
  • 51单片机 IO口模拟串口通讯C程序
  •  本文所说的模拟串口, 就是利用51的两个输入输出引脚如P1.0和P1.1,置1或0分别代表高低电平,也就是串口通信中所说的位,如起始位用低电平,则将其置0,停止位为高电平,则将其置1,各种数据位和校验位则根据情况...

空空如也

空空如也

1 2 3 4 5 ... 14
收藏数 263
精华内容 105
关键字:

51单片机模拟串口