久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5138|回復: 6
收起左側

單片機RS485通信與Modbus協議

  [復制鏈接]
ID:415338 發表于 2021-7-5 22:56 | 顯示全部樓層 |閱讀模式
RS485通信的特點
n1、采用差分信號。
n2、RS485通信速率快,最大傳輸速率可以達到10Mb/s以上。
n3、RS485內部采用平衡驅動器和差分接收器的組合,抗干擾能力大大增加。
n4、傳輸距離最遠可以達到1200米左右。
n5、可以在總線上進行聯網多機通信。
n6、RS485接口非常簡單。
Modbus通信協議介紹
n1、Modbus產生的背景。
n2、Modbus協議特點。
n3、RTU協議幀數據
n4、Modbus功能碼
/* 備  注:
* 1、在lesson15_3的基礎上去掉按鍵校時,添加lesson18_2中的Modbus協議支持
* 2、利用Modbus調試精靈的寫寄存器功能,可修改日期時間的每一個字節
* 3、寄存器地址0x0000~0x0006分別對應“年/月/日/時/分/秒/星期”
* 4、RS485方向控制信號由原來的P1.7改為P2.0,因本例使用了DS1302而未使用按鍵
*******************************************************************************
*/

#include <reg52.h>

struct sTime {  //日期時間結構體定義
    unsigned int  year;
    unsigned char mon;
    unsigned char day;
    unsigned char hour;
    unsigned char min;
    unsigned char sec;
    unsigned char week;
};

bit flag200ms = 1;  //200ms定時標志
bit reqRefresh = 0;  //時間刷新請求
struct sTime bufTime;  //日期時間緩沖區
unsigned char T0RH = 0;  //T0重載值的高字節
unsigned char T0RL = 0;  //T0重載值的低字節

void ConfigTimer0(unsigned int ms);
void RefreshTimeShow();
extern void InitDS1302();
extern void GetRealTime(struct sTime *time);
extern void SetRealTime(struct sTime *time);
extern void UartDriver();
extern void ConfigUART(unsigned int baud);
extern void UartRxMonitor(unsigned char ms);
extern void UartWrite(unsigned char *buf, unsigned char len);
extern unsigned int GetCRC16(unsigned char *ptr,  unsigned char len);
extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);

void main()
{
    unsigned char psec=0xAA;  //秒備份,初值AA確保首次讀取時間后會刷新顯示

    EA = 1;            //開總中斷
    ConfigTimer0(1);   //配置T0定時1ms
    ConfigUART(9600);  //配置波特率為9600
    InitDS1302();      //初始化實時時鐘
    InitLcd1602();     //初始化液晶

    //初始化屏幕上固定不變的內容
    LcdShowStr(3, 0, "20  -  -  ");
    LcdShowStr(4, 1, "  :  :  ");

    while (1)
    {
        UartDriver();  //調用串口驅動
        if (flag200ms)
        {
            flag200ms = 0;
            GetRealTime(&bufTime);    //獲取當前時間
            if (reqRefresh || (psec!=bufTime.sec))
            {   //檢測到時間刷新請求或時間有變化時刷新顯示
                RefreshTimeShow();
                psec = bufTime.sec;   //用當前值更新上次秒數
            }
        }
    }
}
/* 將一個BCD碼字節顯示到屏幕上,(x,y)-屏幕起始坐標,bcd-待顯示BCD碼 */
void ShowBcdByte(unsigned char x, unsigned char y, unsigned char bcd)
{
    unsigned char str[4];

    str[0] = (bcd >> 4) + '0';
    str[1] = (bcd&0x0F) + '0';
    str[2] = '\0';
    LcdShowStr(x, y, str);
}
/* 刷新日期時間的顯示 */
void RefreshTimeShow()
{
    ShowBcdByte(5,  0, bufTime.year);
    ShowBcdByte(8,  0, bufTime.mon);
    ShowBcdByte(11, 0, bufTime.day);
    ShowBcdByte(4,  1, bufTime.hour);
    ShowBcdByte(7,  1, bufTime.min);
    ShowBcdByte(10, 1, bufTime.sec);
}
/* 串口動作函數,根據接收到的命令幀執行響應的動作
   buf-接收到的命令幀指針,len-命令幀長度 */
void UartAction(unsigned char *buf, unsigned char len)
{
    unsigned int  crc;
    unsigned char crch, crcl;

    if (buf[0] != 0x01) //本例中的本機地址設定為0x01,
    {                   //如數據幀中的地址字節與本機地址不符,
        return;         //則直接退出,即丟棄本幀數據不做任何處理
    }
    //地址相符時,再對本幀數據進行校驗
    crc = GetCRC16(buf, len-2);  //計算CRC校驗值
    crch = crc >> 8;
    crcl = crc & 0xFF;
    if ((buf[len-2]!=crch) || (buf[len-1]!=crcl))
    {
        return;   //如CRC校驗不符時直接退出
    }
    //地址和校驗字均相符后,解析功能碼,執行相關操作
    switch (buf[1])
    {
        case 0x06:  //寫入單個寄存器
            if ((buf[2]==0x00) && (buf[3]<=0x06)) //地址0x0000~0x0006分別對應
            {                                     // “年/月/日/時/分/秒/星期”
                GetRealTime(&bufTime);  //獲取當前時間
                switch (buf[3])  //由寄存器地址決定要修改的時間位
                {
                    case 0: bufTime.year = 0x2000 + buf[5]; break;
                    case 1: bufTime.mon  = buf[5]; break;
                    case 2: bufTime.day  = buf[5]; break;
                    case 3: bufTime.hour = buf[5]; break;
                    case 4: bufTime.min  = buf[5]; break;
                    case 5: bufTime.sec  = buf[5]; break;
                    case 6: bufTime.week = buf[5]; break;
                    default: break;
                }
                SetRealTime(&bufTime);  //寫入新修改后的時間
                reqRefresh = 1;  //設置顯示刷新請求
                len -= 2;  //長度-2以重新計算CRC并返回原幀
                break;
            }
            else  //寄存器地址不被支持時,返回錯誤碼
            {
                buf[1] = 0x86;  //功能碼最高位置1
                buf[2] = 0x02;  //設置異常碼為02-無效地址
                len = 3;
                break;
            }

        default:  //其它不支持的功能碼
            buf[1] |= 0x80;  //功能碼最高位置1
            buf[2] = 0x01;   //設置異常碼為01-無效功能
            len = 3;
            break;
    }
    crc = GetCRC16(buf, len); //計算返回幀的CRC校驗值
    buf[len++] = crc >> 8;    //CRC高字節
    buf[len++] = crc & 0xFF;  //CRC低字節
    UartWrite(buf, len);      //發送返回幀
}
/* 配置并啟動T0,ms-T0定時時間 */
void ConfigTimer0(unsigned int ms)
{
    unsigned long tmp;  //臨時變量

    tmp = 11059200 / 12;      //定時器計數頻率
    tmp = (tmp * ms) / 1000;  //計算所需的計數值
    tmp = 65536 - tmp;        //計算定時器重載值
    tmp = tmp + 33;           //補償中斷響應延時造成的誤差
    T0RH = (unsigned char)(tmp>>8);  //定時器重載值拆分為高低字節
    T0RL = (unsigned char)tmp;
    TMOD &= 0xF0;   //清零T0的控制位
    TMOD |= 0x01;   //配置T0為模式1
    TH0 = T0RH;     //加載T0重載值
    TL0 = T0RL;
    ET0 = 1;        //使能T0中斷
    TR0 = 1;        //啟動T0
}
/* T0中斷服務函數,執行按鍵掃描和200ms定時 */
void InterruptTimer0() interrupt 1
{
    static unsigned char tmr200ms = 0;

    TH0 = T0RH;  //重新加載重載值
    TL0 = T0RL;
    UartRxMonitor(1);  //串口接收監控
    tmr200ms++;
    if (tmr200ms >= 200)  //定時200ms
    {
        tmr200ms = 0;
        flag200ms = 1;
    }
}

Modbus注意要項.pdf

216.87 KB, 下載次數: 96, 下載積分: 黑幣 -5

MODBUS協議中文版.pdf

1.11 MB, 下載次數: 114, 下載積分: 黑幣 -5

Modbus通信協議.pdf

156.79 KB, 下載次數: 88, 下載積分: 黑幣 -5

MAX485.pdf

438.77 KB, 下載次數: 85, 下載積分: 黑幣 -5

例程.7z

18.93 KB, 下載次數: 138, 下載積分: 黑幣 -5

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

回復

使用道具 舉報

ID:624685 發表于 2021-7-6 10:16 | 顯示全部樓層
資料真好,就是有點非 錢啊
回復

使用道具 舉報

ID:415338 發表于 2021-7-7 15:16 | 顯示全部樓層
沒積分,需要資料的可以直接私信我,我發你
回復

使用道具 舉報

ID:686788 發表于 2021-7-7 16:25 | 顯示全部樓層
很好的資料,感謝分享,頂!!!
回復

使用道具 舉報

ID:373892 發表于 2022-3-12 09:51 | 顯示全部樓層
遠小劉 發表于 2021-7-7 15:16
沒積分,需要資料的可以直接私信我,我發你

求發915572320@qq.com,謝謝樓主
回復

使用道具 舉報

ID:99525 發表于 2022-5-4 04:05 | 顯示全部樓層
這就是宋老師第十八章的內容!
回復

使用道具 舉報

ID:18797 發表于 2022-6-10 00:07 | 顯示全部樓層
好貼,有一定的借鑒意義
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩精品中文字幕在线 | 大吊一区二区 | 在线中文字幕日韩 | 少妇一级淫片免费播放 | 日韩毛片在线视频 | 91久久网站 | 爱高潮www亚洲精品 中文字幕免费视频 | 国产乱码久久久 | 国产欧美一级二级三级在线视频 | 国产一级在线 | 日韩成人免费中文字幕 | 亚洲国产精品一区在线观看 | 国产日韩精品视频 | 国产成人精品网站 | 亚洲精选一区二区 | 亚洲一二三区在线观看 | 国产精品视频一区二区三区 | 亚洲视频一区二区三区四区 | 亚洲欧美日韩精品久久亚洲区 | 成人午夜视频在线观看 | 日韩三级在线 | 国产目拍亚洲精品99久久精品 | 天天夜夜人人 | 国产综合在线视频 | 久久婷婷av | 欧洲一区在线观看 | 欧美精品一区二区在线观看 | 亚洲成年人免费网站 | 中文字幕一区在线观看视频 | 欧美日批| 久草视 | 国产成人99久久亚洲综合精品 | 国产三级| 国产亚洲欧美在线视频 | 中文字幕一区二区三区日韩精品 | 毛片入口 | 免费观看一级特黄欧美大片 | 亚洲成人播放器 | 国产精品福利在线 | 免费观看一级毛片 | 亚洲成av人片在线观看 |