STC学习:485双机通信

Posted 18890394937

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STC学习:485双机通信相关的知识,希望对你有一定的参考价值。

程序设计目标及程序运行效果说明
程序设计目标:通过本例程理解RS485通信方式,实现双机通信。
程序运行效果:将两块带有485模块的51单片机通过485外接引脚A、B连接起来,单片机上电烧写程序后485模块的D/R引脚所对应的二极管均点亮,然后通过按键KEY3、KEY2控制数码管上的数值进行加减处理,两块单片机起始都默认为接收状态,最后按下KEY1发送键,将数据传送给另一块单片机,而此时接收方数码管上的数值发生相应的改变,与发送方数码管上的数值一致。

程序相关电路及工作原理说明
1.RS485通信原理
RS232接口是1970年由美国电子工业协会(EIA)联合贝尔系统、 调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。针对RS232的不足,于是不断出现了新的接口标准,RS485就是其中的一种。 RS485接口的最大传输距离标准值为4000英尺,实际上可达 3000米,另外RS232接口在总线上只允许连接1个收发器, 即单站能力。而RS485接口在总线上是允许连接多达128个收发器。即具有多站能力,这样用户可以利用单一的RS485接口方便地建立起设备网络。

RS485属于半双工通信,数据可以在一个信号载体的两个方向上传输,但是不能同时进行传输。电平转换采用差分电路方式,A、B两线的电压差大于0.2认为是逻辑“1”,小于-0.2认为是逻辑“0”,方便与TTL电路连接。使用RS485进行通信与RS232通信的逻辑是一致的,但RS485抗干扰性更强,传输距离更远。RS485广泛运用在工业自动化控制、视频监控、门禁对讲以及楼宇报警等各个领域。

MAX485芯片的功能是将TTL电平转换为RS485电平,引脚功能如下:
(1)485 D/R输出、接收信号控制引脚:当该引脚为低电平时,485为接收态,MAX485通过485_RXD把来自u总线的信号输出给单片机;当该引脚为高电平时,485为发送态,来自485_TXD的输出信号通过A、B引脚加载到总线上。
(2)485_RXD引脚接收数据,RX1 LED点亮时表示正在接收数据。
(3)485_TXD引脚发送数据,TX1 LED点亮时表示正在发送数据。
(4)A、B端口与另一个开发板上的MAX485的A、B连接实现双机通信。
使用RS485进行通信的大致步骤为:
(1)初始化波特率,设置好串口通信模式;
(2)发送数据时将数据放入S2BUF,并软件清零S2RI;
(3)接收数据时从S2BUF读取数据,并软件清零S2TI。

2.数码管显示原理
通过LED_SEL控制74HC138的使能信号E3,并结合A0、A1、A2三个位选控制信号确定八个数码管中的哪一个数码管被点亮;该模块采用八段共阴极数码管,P0口的八个段选控制信号确定任意一个数码管八段中的哪一段被点亮。

3.按键控制原理
本案例中,按键1引脚对应触发外部中断0,通过设定寄存器设置按键1下降沿触发外部中断,当按键1被按下时启动数据发送;按键2和按键3实现数码管上的数值加减,当单片机检测到引脚为低电平时,对数码管数值进行操作。按键部分需要考虑按键的消抖问题,本程序采用延时消抖。另外在本案例中使用按键中断服务程序实现数据发送的,因此串口中断的优先级高于按键中断。

测试方法

  1. 将两块带485模块的板子通过485外接引脚连接起来;注意不要交叉连接(数据传输错误)
  2. 按照“工程建立及下载到开发板整个流程指导.doc”文件将当前目录的Hex文件下载到两块开发版上,两块开发板默认最右边数码管均显示0;485模块的D/R对应二极管均点亮;
  3. 通过key2或者key3调整数值(数码管会显示出来)如“c”,按下key1,完成一块单片机向另一块单片机发送数据。

双机通信流程图

相关寄存器配置
1.选择485芯片引脚
P_SW2:外围设备功能切换控制寄存器2(不可位寻址)

串口2可在2个地方切换,由S2_S控制位来选择


该开发板485芯片使用串口2的第2组引脚:

P_SW2 |= 0x01 ;

2.设置串口2的工作模式
S2CON:串行口2的控制寄存器

S2SM0指定串行口2的工作方式

设置串行口2为:8位UART,波特率可变;允许串行口2接收
S2CON = 0x10 ;

3.选择定时器工作模式
AUCR:辅助寄存器(不可位寻址)

T2R:定时器2运行控制位

T2_C/T:控制定时器2用作定时器或计数器;

T2x12:定时器2速度控制位。

设置定时器2为1T模式,并启动定时器2

AUXR |= 0x14 ;

4.串行口2中断允许
IE2:中断允许寄存器2(不可位寻址)

ES2为串行口2中断允许位

IE:中断允许寄存器(可位寻址)中的EA为CPU的总中断允许控制位。

允许串行口2中断:

IE2 |= 0x01 ;

EA = 1 ;

代码如下:

#include<STC15F2K60S2.H>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
#define cstUart2Ri 0x01                        //接收中断请求标志位
#define cstUart2Ti 0x02                        //发送中断请求标志位
#define cstNoneParity 0                  //无校验
#define PARITYBIT cstNoneParity         //定义校验位
/*串口波特率相关*/
#define cstFosc 11059200L               //系统时钟频率 
#define cstBaud2 9600                    //串口波特率    
#define cstT2HL (65536-(cstFosc/4/cstBaud2))    //定时器初始时间
sbit sbtKey1=P3^2;                //启动发送
sbit sbtKey2=P3^3;                //数字减少
sbit sbtKey3=P1^7;                //数字增加
sbit sbtSel0=P2^0;
sbit sbtSel1=P2^1;
sbit sbtSel2=P2^2;
sbit sbtLedSel=P2^3;
sbit sbtM485_TRN=P3^7 ;   //定义MAX485使能引脚,为1时发送,为0时接收
bit btSendBusy;                            //为1时忙(发送数据),为0时闲
uchar ucGetDataTmp;          //接收数据暂存
uchar ucPutDataTmp;          //发送数据暂存
uchar arrSegSelect[]={0x3f, 0x06, 0x5b, 0x4f, 0x66,
                      0x6d, 0x7d, 0x07, 0x7f, 0x6f,
                      0x77, 0x7c, 0x39, 0x5e, 0x79,
                      0x71, 0x40, 0x00
                      };//段选,显示0-f
//串口2初始化及波特率发生函数
void Uart2Init()
{
    S2CON=0x10;      //定义无校验位,允许串行口2接收
    T2L=cstT2HL;             //设置波特率重装值
    T2H=cstT2HL>>8;
    AUXR|=0x14;      //T2为1T模式,并启动定时器2
}
//系统硬件、变量初始化函数
void Init()
{
    P0M0=0xff;       //P0口推挽(放大电流)
    P0M1=0x00;
    P2M0=0x0f;       //P2.0—~P2.3口推挽
    P2M1=0x00;
    P3M0=0x00;
    P3M1=0x00;
    P1M0=0x00;
    P1M1=0x00;       //P1、P3准双向口
    //外部中断0
    IT0=1;           //下降沿触发中断(为0则下降沿和上升沿均会触发中断)
    EX0=1;           //允许外部中断0
    PX0=0;           //外部中断:低优先级
    //485初始化  波特率生成
    sbtM485_TRN=0;       //初始为接收状态
    P_SW2|=0x01;     //切换串口2的管脚到P4.6,P4.7
    Uart2Init();
    btSendBusy=1;
    IE2|=0x01;       //开串行口2中断
    IP2|=0x01;       //设置串行口中断:高优先级
    EA=1;            //开总中断
    //数码管选择
    sbtLedSel=0;     //开启数码管显示
    sbtSel0=1;
    sbtSel1=1;
    sbtSel2=1;           //选择第八位数码管显示
    ucPutDataTmp=0;
}
void delay()
{
    uchar i,j;
    for(i=0;i<255;i++)
        for(j=0;j<255;j++);
}
//串口2中断处理程序
void Uart2_Process()interrupt 8 using 1
{
    if(S2CON&cstUart2Ri)
    {
        ucGetDataTmp=S2BUF ;
        ucPutDataTmp=ucGetDataTmp ;
        S2CON&=~cstUart2Ri;   //接收中断标志位清0
    }
    if(S2CON&cstUart2Ti)
    {
        btSendBusy=0;            //清除忙信号
        S2CON&=~cstUart2Ti ;      //发送中断标志位清0
    }
}
//外部中断0处理程序
void ExInt0_Process()interrupt 0
{
    sbtM485_TRN=1;
    S2BUF=ucPutDataTmp;
    while(btSendBusy);
    btSendBusy=1;
    sbtM485_TRN=0;
}
void main()
{
    Init();
    while(1)
    {
        ucPutDataTmp%=16;
        P0=arrSegSelect[ucPutDataTmp];
        if(sbtKey3==0)
        {
            delay();
            if(sbtKey3==0)
            {
                while(!sbtKey3);
                ucPutDataTmp++;
            }
        }
        if(sbtKey2==0)
        {
            delay();
            if(sbtKey2==0)
            {
                while(!sbtKey2);
                ucPutDataTmp--;
            }
        }
    }
}

以上是关于STC学习:485双机通信的主要内容,如果未能解决你的问题,请参考以下文章

串口实现双机通信

STM32 和 STC单片机SPI通信字节最后一位出错

STC89C52单片机串行通信异常

学习7__STM32--SPI外设之双机通信---

关于STC单片机的内存管理

STC学习:串口通信