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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

我的 modbus 從機板 開發代碼

[復制鏈接]
跳轉到指定樓層
樓主
ID:115923 發表于 2020-2-21 16:56 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
/***************************Lcd1602.c文件程序源代碼*****************************/

(此處省略,可參考之前章節的代碼)

/****************************RS485.c文件程序源代碼*****************************/

(此處省略,可參考之前章節的代碼)

/****************************CRC16.c文件程序源代碼****************************/

/* CRC16計算函數,ptr-數據指針,len-數據長度,返回值-計算出的CRC16數值 */

unsigned int GetCRC16(unsigned char *ptr,  unsigned char len)

{

    unsigned int index;

    unsigned char crch = 0xFF;  //高CRC字節

    unsigned char crcl = 0xFF;  //低CRC字節

    unsigned char code TabH[] = {  //CRC高位字節值表

        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  

        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  

        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  

        0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  

        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  

        0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,  

        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  

        0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  

        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  

        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  

        0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  

        0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  

        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  

        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  

        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  

        0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,  

        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  

        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  

        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  

        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  

        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,  

        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,  

        0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,  

        0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,  

        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,  

        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40  

    } ;  

    unsigned char code TabL[] = {  //CRC低位字節值表

        0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,  

        0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,  

        0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,  

        0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,  

        0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,  

        0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,  

        0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,  

        0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,  

        0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,  

        0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,  

        0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,  

        0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,  

        0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,  

        0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,  

        0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,  

        0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,  

        0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,  

        0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,  

        0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,  

        0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,  

        0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,  

        0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,  

        0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,  

        0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,  

        0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,  

        0x43, 0x83, 0x41, 0x81, 0x80, 0x40  

    } ;



    while (len--)  //計算指定長度的CRC

    {

        index = crch ^ *ptr++;

        crch = crcl ^ TabH[index];

        crcl = TabL[index];

    }



    return ((crch<<8) | crcl);  

}

關于CRC校驗的算法,如果不是專門學習校驗算法本身,大家可以不去研究這個程序的細節,直接使用現成的函數即可。

/*****************************main.c文件程序源代碼******************************/

#include
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)  // 01 03 [ 00  i ]  [ xx cnt ] [ crch crcl ]
                {
                    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)  // 01 06 [ 00  i ]  [ xx regG ] [ crch crcl ]
                {
                    i = buf[3];               //提取寄存器地址
                    regGroup = buf[5];   //保存寄存器數據
                    cnt = regGroup >> 4; //顯示到液晶上  16進制轉string
                    if (cnt >= 0xA)
                        str[0] = cnt - 0xA + 'A';
                    else
                        str[0] = cnt + '0';
                    cnt = regGroup & 0x0F;
                    if (cnt >= 0xA)
                        str[1] = cnt - 0xA + 'A';
                    else
                        str[1] = cnt + '0';
                    str[2] = '';
                    LcdShowStr(i*3, 0, str);
                }

                else  //地址0x05為蜂鳴器狀態 // 01 06 [ 00  05 ]  [ xx  on ] [ crch crcl ]
                {
                    flagBuzzOn = (bit)buf[5]; //寄存器值轉為蜂鳴器的開關
                }

                len -= 2; //長度-2以重新計算CRC并返回原幀
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 九九综合 | 精品视频在线观看 | 日本久久久久久 | 91在线观看视频 | 日韩在线观看精品 | 色婷婷狠狠 | 国产精品日韩欧美一区二区三区 | 成人日韩精品 | 久久精品一区二区三区四区 | 91看国产| 91在线成人 | 亚洲欧美日本在线 | 91 在线| 久久美女网 | 又爽又黄axxx片免费观看 | 久久久一区二区三区 | 久久草视频 | 久久久噜噜噜www成人网 | 国产精品久久亚洲 | 日本粉嫩一区二区三区视频 | 中文字幕乱码视频32 | 亚洲综合视频 | 中文字幕一级 | 中文字幕1区2区3区 亚洲国产成人精品女人久久久 | 国产成人高清成人av片在线看 | 日韩一二三 | 国产欧美一区二区三区在线播放 | 日韩第一页 | av官网在线 | 欧美一级艳情片免费观看 | 久久久久国产精品一区三寸 | 国产午夜视频 | 在线永久看片免费的视频 | 夜久久 | 精品久久香蕉国产线看观看亚洲 | 一区二区三区四区在线 | 一区二区在线不卡 | 亚洲中字在线 | 国产精品无码专区在线观看 | 一区二区三区免费看 | 欧美一级黑人aaaaaaa做受 |