标题: 谁能教教我用RS485,max485,芯片 怎么和C52单片机建立通讯!程序怎么写! [打印本页]

作者: ntq9527    时间: 2018-11-22 10:39
标题: 谁能教教我用RS485,max485,芯片 怎么和C52单片机建立通讯!程序怎么写!
如题
作者: lygxnb    时间: 2018-11-22 19:01
单片机的P30和P31接MAX485的RO和DI就完成建立了,具体通信协议就看软件来实现了。
作者: 封小墨    时间: 2018-11-22 20:51
RxD和TxD接RO和DI就好了,程序要慢慢来啊
作者: jindizhiwa    时间: 2018-11-22 21:48
单片机的P30和P31接MAX485的RO和DI就完成建立了,再用一个IO口控制RE/DE,程序就是串口发送接收,注意RE/DE的读写方向

485.png (21 KB, 下载次数: 123)

485.png

code.zip

2.53 KB, 下载次数: 124


作者: qw6564    时间: 2018-11-22 22:52
片机的P30和P31接MAX485的RO和DI就完成建立
作者: 远征之路    时间: 2018-11-23 08:34
以下为具体实现通信的程序:
//RS485查询接收到的数据
//buf:接收缓存首地址
//len:读到的数据长度
void RS485_Receive_Data(u8 *buf,u8 *len)
{
        u8 rxlen=RS485_RX_CNT;
        u8 i=0;
        *len=0;                                //默认为0
        delay_ms(10);                //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
        if(rxlen==RS485_RX_CNT&&rxlen)//接收到了数据,且接收完成了
        {
                for(i=0;i<rxlen;i++)
                {
                        buf[ i]=RS485_RX_BUF[ i];                        }                                *len=RS485_RX_CNT;        //记录本次数据长度                RS485_RX_CNT=0;                //清零        }}
作者: Host    时间: 2018-11-23 10:15
正好最近做了一个
作者: Host    时间: 2018-11-23 10:19
仿真图如图所示:程序:
#include <reg51.h>
#include <intrins.h>
#include "12864.c"

sbit REDE=P1^0;

//void delay(void)
//{
//     unsigned int i,j;
//         for(i=0;i<200;i++)
//           for(j=0;j<500;j++)  ;
//}
//
//void Send(unsigned char dat)
//{
//    SBUF=dat;
//        while(TI==0);
//        TI=0;
//}

void main(void)
{
    TMOD=0x20;
        SCON=0x50;
        PCON=0x00;
        TH1=0xFD;
        TR1=1;
        REN=1;
        EA=1;
        ES=1;
        LCD_Init();
        REDE=0;
    while(1);
// {
//         Send(0x23);
//        Send(0x31);
//        Send(0x32);
//        Send(0x0D);
//        delay();
// }
}

void Uart_Serve(void) interrupt 4 using 0
{
   if(RI==1)
   {
           RI=0;
        DisplayResult(SBUF);
   }
}


//12864的程序不需要赘述了吧

1.png (40.49 KB, 下载次数: 133)

1.png

作者: mrhan1992    时间: 2018-11-23 10:58
根据RS485串口通讯协议,按照协议要求来操作TXD和RXD
作者: 你从哪来    时间: 2020-3-12 14:53
原理图按照三楼的那样连接,程序如下:
#include <reg52.h>
#include <intrins.h>

sbit RS485_DIR = P1^7;  //RS485方向选择引脚

bit flagFrame = 0;  //帧接收完成标志,即接收到一帧新数据
bit flagTxd = 0;    //单字节发送完成标志,用来替代TXD中断标志位
unsigned char cntRxd = 0;   //接收字节计数器
unsigned char pdata bufRxd[64];  //接收字节缓冲区

extern void UartAction(unsigned char *buf, unsigned char len);

/* 串口配置函数,baud-通信波特率 */
void ConfigUART(unsigned int baud)
{
    RS485_DIR = 0; //RS485设置为接收方向
    SCON  = 0x50;  //配置串口为模式1
    TMOD &= 0x0F;  //清零T1的控制位
    TMOD |= 0x20;  //配置T1为模式2
    TH1 = 256 - (11059200/12/32)/baud;  //计算T1重载值
    TL1 = TH1;     //初值等于重载值
    ET1 = 0;       //禁止T1中断
    ES  = 1;       //使能串口中断
    TR1 = 1;       //启动T1
}
/* 软件延时函数,延时时间(t*10)us */
void DelayX10us(unsigned char t)
{
    do {
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
    } while (--t);
}
/* 串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度 */
void UartWrite(unsigned char *buf, unsigned char len)
{
    RS485_DIR = 1;  //RS485设置为发送
    while (len--)   //循环发送所有字节
    {
        flagTxd = 0;      //清零发送标志
        SBUF = *buf++;    //发送一个字节数据
        while (!flagTxd); //等待该字节发送完成
    }
    DelayX10us(5);  //等待最后的停止位完成,延时时间由波特率决定
    RS485_DIR = 0;  //RS485设置为接收
}
/* 串口数据读取函数,buf-接收指针,len-指定的读取长度,返回值-实际读到的长度 */
unsigned char UartRead(unsigned char *buf, unsigned char len)
{
    unsigned char i;
   
    if (len > cntRxd)  //指定读取长度大于实际接收到的数据长度时,
    {                  //读取长度设置为实际接收到的数据长度
        len = cntRxd;
    }
    for (i=0; i<len; i++)  //拷贝接收到的数据到接收指针上
    {
        *buf++ = bufRxd[i];
    }
    cntRxd = 0;  //接收计数器清零
   
    return len;  //返回实际读取长度
}
/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
void UartRxMonitor(unsigned char ms)
{
    static unsigned char cntbkp = 0;
    static unsigned char idletmr = 0;

    if (cntRxd > 0)  //接收计数器大于零时,监控总线空闲时间
    {
        if (cntbkp != cntRxd)  //接收计数器改变,即刚接收到数据时,清零空闲计时
        {
            cntbkp = cntRxd;
            idletmr = 0;
        }
        else                   //接收计数器未改变,即总线空闲时,累积空闲时间
        {
            if (idletmr < 30)  //空闲计时小于30ms时,持续累加
            {
                idletmr += ms;
                if (idletmr >= 30)  //空闲时间达到30ms时,即判定为一帧接收完毕
                {
                    flagFrame = 1;  //设置帧接收完成标志
                }
            }
        }
    }
    else
    {
        cntbkp = 0;
    }
}
/* 串口驱动函数,监测数据帧的接收,调度功能函数,需在主循环中调用 */
void UartDriver()
{
    unsigned char len;
    unsigned char pdata buf[40];

    if (flagFrame) //有命令到达时,读取处理该命令
    {
        flagFrame = 0;
        len = UartRead(buf, sizeof(buf)-2); //将接收到的命令读取到缓冲区中
        UartAction(buf, len);  //传递数据帧,调用动作执行函数
    }
}
/* 串口中断服务函数 */
void InterruptUART() interrupt 4
{
    if (RI)  //接收到新字节
    {
        RI = 0;  //清零接收中断标志位
        if (cntRxd < sizeof(bufRxd)) //接收缓冲区尚未用完时,
        {                            //保存接收字节,并递增计数器
            bufRxd[cntRxd++] = SBUF;
        }
    }
    if (TI)  //字节发送完毕
    {
        TI = 0;   //清零发送中断标志位
        flagTxd = 1;  //设置字节发送完成标志
    }
}





欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1