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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4467|回復: 1
打印 上一主題 下一主題
收起左側

基于RS485的Modbus通信示例

[復制鏈接]
跳轉到指定樓層
樓主
ID:164629 發表于 2017-2-18 16:33 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式


#include <reg52.h>

sbit BUZZ = P1^6;

bit flagBuzzOn = 0;   //蜂鳴器啟動標志
unsigned char T0RH = 0;  //T0重載值的高字節
unsigned char T0RL = 0;  //T0重載值的低字節
unsigned char regGroup[5];  //Modbus寄存器組,地址為0x00~0x04

void ConfigTimer0(unsigned int ms);
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()
{
    EA = 1;            //開總中斷
    ConfigTimer0(1);   //配置T0定時1ms
    ConfigUART(9600);  //配置波特率為9600
    InitLcd1602();     //初始化液晶
   
    while (1)
    {
        UartDriver();  //調用串口驅動
    }
}
/* 串口動作函數,根據接收到的命令幀執行響應的動作
   buf-接收到的命令幀指針,len-命令幀長度 */
void UartAction(unsigned char *buf, unsigned char len)
{
    unsigned char i;
    unsigned char cnt;
    unsigned char str[4];
    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 0x03:  //讀取一個或連續的寄存器
            if ((buf[2]==0x00) && (buf[3]<=0x05)) //只支持0x0000~0x0005
            {
                if (buf[3] <= 0x04)
                {
                    i = buf[3];      //提取寄存器地址
                    cnt = buf[5];    //提取待讀取的寄存器數量
                    buf[2] = cnt*2;  //讀取數據的字節數,為寄存器數*2
                    len = 3;         //幀前部已有地址、功能碼、字節數共3個字節
                    while (cnt--)
                    {
                        buf[len++] = 0x00;          //寄存器高字節補0
                        buf[len++] = regGroup[i++]; //寄存器低字節
                    }
                }
                else  //地址0x05為蜂鳴器狀態
                {
                    buf[2] = 2;  //讀取數據的字節數
                    buf[3] = 0x00;
                    buf[4] = flagBuzzOn;
                    len = 5;
                }
                break;
            }
            else  //寄存器地址不被支持時,返回錯誤碼
            {
                buf[1] = 0x83;  //功能碼最高位置1
                buf[2] = 0x02;  //設置異常碼為02-無效地址
                len = 3;
                break;
            }
            
        case 0x06:  //寫入單個寄存器
            if ((buf[2]==0x00) && (buf[3]<=0x05)) //只支持0x0000~0x0005
            {
                if (buf[3] <= 0x04)
                {
                    i = buf[3];             //提取寄存器地址
                    regGroup[i] = buf[5];   //保存寄存器數據
                    cnt = regGroup[i] >> 4; //顯示到液晶上
                    if (cnt >= 0xA)
                        str[0] = cnt - 0xA + 'A';
                    else
                        str[0] = cnt + '0';
                    cnt = regGroup[i] & 0x0F;
                    if (cnt >= 0xA)
                        str[1] = cnt - 0xA + 'A';
                    else
                        str[1] = cnt + '0';
                    str[2] = '\0';
                    LcdShowStr(i*3, 0, str);
                }
                else  //地址0x05為蜂鳴器狀態
                {
                    flagBuzzOn = (bit)buf[5]; //寄存器值轉為蜂鳴器的開關
                }
                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中斷服務函數,執行串口接收監控和蜂鳴器驅動 */
void InterruptTimer0() interrupt 1
{
    TH0 = T0RH;  //重新加載重載值
    TL0 = T0RL;
    if (flagBuzzOn)  //執行蜂鳴器鳴叫或關閉
        BUZZ = ~BUZZ;
    else
        BUZZ = 1;
    UartRxMonitor(1);  //串口接收監控
}

評分

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

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:366088 發表于 2018-7-6 16:24 | 只看該作者
程序有殘缺吧,有些函數被寫出來了但是沒有調用
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩精品在线观看网站 | 天天草天天 | 色伊人久久 | 亚洲欧美中文日韩在线v日本 | 亚洲精品久久久一区二区三区 | 天天干天天想 | 在线国产一区二区 | 久久se精品一区精品二区 | 黄网站涩免费蜜桃网站 | 中文字幕精品视频 | 亚洲婷婷一区 | 亚洲精品日韩一区二区电影 | 精品久久久久久18免费网站 | 国产精品免费在线 | 日韩和的一区二在线 | 欧美视频精品 | av片网| 日韩国产一区二区三区 | 亚洲欧洲国产视频 | 久久大 | 国产一区二区三区视频免费观看 | 黄色在线观看 | 亚洲国产精品久久久久婷婷老年 | 日韩av免费在线电影 | 日日骚网 | 精品久久久久久亚洲综合网 | 国产视频久久 | 成人一区二区视频 | 四虎海外 | 日韩欧美成人精品 | 中国一级特黄毛片大片 | 午夜男人天堂 | 欧洲色综合 | 亚洲成人av在线播放 | 精品一区二区久久久久久久网站 | 韩日在线视频 | 97精品视频在线观看 | 午夜精品一区 | 中文字幕国产高清 | 在线免费看黄 | 99国内精品久久久久久久 |