国产成人av人人爽人人澡-亚洲国产日韩欧美一区-好吊日视频这里只有精品-日本高清精品视频在线

你好!歡迎來(lái)到深圳市穎特新科技有限公司!
語(yǔ)言
當(dāng)前位置:首頁(yè) >> 技術(shù)中心 >> 單片機(jī)入門(mén) >> Modbus多機(jī)通信例程

Modbus多機(jī)通信例程

作者:admin 來(lái)源:不詳 發(fā)布時(shí)間:2018-05-08  瀏覽:21

  給從機(jī)下發(fā)不同的指令,從機(jī)去執(zhí)行不同的操作,這個(gè)就是判斷一下功能碼即可,和我們前邊學(xué)的實(shí)用串口例程是類(lèi)似的。多機(jī)通信,無(wú)非就是添加了一個(gè)設(shè)備地址判斷而已,難度也不是很大。我們找了一個(gè)Modbus調(diào)試精靈,通過(guò)設(shè)置設(shè)備地址,讀寫(xiě)寄存器的地址以及數(shù)值數(shù)量等參數(shù),可以直接替代串口調(diào)試助手,比較方便的下發(fā)多個(gè)字節(jié)的數(shù)據(jù),如圖1所示。我們先來(lái)就圖中的設(shè)置和數(shù)據(jù)來(lái)對(duì)Modbus做進(jìn)一步的分析,圖中的數(shù)據(jù)來(lái)自于調(diào)試精靈與我們接下來(lái)要講的例程之間的交互。

Modbus調(diào)試精靈

圖1 Modbus調(diào)試精靈

  如圖:我們的USB轉(zhuǎn)485模塊虛擬出的是COM5,波特率9600,無(wú)校驗(yàn)位,數(shù)據(jù)位是8位,1位停止位,設(shè)備地址假設(shè)為1。

  寫(xiě)寄存器的時(shí)候,如果我們要把01寫(xiě)到一個(gè)地址是0000的寄存器地址里,點(diǎn)一下“寫(xiě)入”,就會(huì)出現(xiàn)發(fā)送指令:01 06 00 00 00 01 48 0A。我們來(lái)分析一下這幀數(shù)據(jù),其中01是設(shè)備地址,06是功能碼,代表寫(xiě)寄存器這個(gè)功能,后邊跟00 00表示的是要寫(xiě)入的寄存器的地址,00 01就是要寫(xiě)入的數(shù)據(jù),48 0A就是CRC校驗(yàn)碼,這是軟件自動(dòng)算出來(lái)了。而根據(jù)Modbus協(xié)議,當(dāng)寫(xiě)寄存器的時(shí)候,從機(jī)成功完成該指令的操作后,會(huì)把主機(jī)發(fā)送的指令直接返回,我們的調(diào)試精靈會(huì)接收到這樣一幀數(shù)據(jù):01 06 00 00 00 01 48 0A。

  假如我們現(xiàn)在要從寄存器地址0002開(kāi)始讀取寄存器,并且讀取的數(shù)量是2個(gè)。點(diǎn)一下“讀出”,就會(huì)出現(xiàn)發(fā)送指令:01 03 00 02 00 02 65 CB。其中01是設(shè)備地址,03是功能碼,代表寫(xiě)寄存器這個(gè)功能,00 02就是讀寄存器的起始地址,后一個(gè)00 02就是要讀取2個(gè)寄存器的數(shù)值,65 CB就是CRC校驗(yàn)。而接收到的數(shù)據(jù)是:01 03 04 00 00 00 00 FA 33。其中01是設(shè)備地址,03是功能碼,04代表的是后邊讀到的數(shù)據(jù)字節(jié)數(shù)是4個(gè),00 00 00 00分別是地址為00 02和00 03的寄存器內(nèi)部的數(shù)據(jù),而FA 33就是CRC校驗(yàn)了。

  似乎越來(lái)越明朗了,所謂的Modbus這種通信協(xié)議,無(wú)非就是主機(jī)下發(fā)了不同的指令,從機(jī)根據(jù)指令的判斷來(lái)執(zhí)行不同的操作而已。由于我們的開(kāi)發(fā)板沒(méi)有Modbus功能碼那么多相應(yīng)的功能,我們?cè)诔绦蛑卸x了一個(gè)數(shù)組regGroup[5],相當(dāng)于5個(gè)寄存器,此外又定義了第6個(gè)寄存器,控制蜂鳴器,通過(guò)下發(fā)不同的指令我們改變寄存器組的數(shù)據(jù)或者改變蜂鳴器的開(kāi)關(guān)狀態(tài)。在Modbus協(xié)議里寄存器的地址和數(shù)值都是16位的,即2個(gè)字節(jié),我們默認(rèn)高字節(jié)是0x00,低字節(jié)就是數(shù)組regGroup對(duì)應(yīng)的值。其中地址0x0000到0x0004對(duì)應(yīng)的就是regGroup數(shù)組中的元素,我們寫(xiě)入的同時(shí)把數(shù)字又顯示到我們的LCD1602液晶上,而0x0005這個(gè)地址,寫(xiě)入0x00,蜂鳴器就不響,寫(xiě)入任何其他數(shù)字,蜂鳴器就報(bào)警。我們單片機(jī)的主要工作也就是解析串口接收的數(shù)據(jù)執(zhí)行不同操作,也就是主要在RS485.C這個(gè)文件中了

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

#include <reg52.h>

#include <intrins.h>

 

sbit RS485_DIR = P1^7;  //RS485方向選擇引腳

 

bit flagOnceTxd = 0;  //單次發(fā)送完成標(biāo)志,即發(fā)送完一個(gè)字節(jié)

bit cmdArrived = 0;   //命令到達(dá)標(biāo)志,即接收到上位機(jī)下發(fā)的命令

unsigned char cntRxd = 0;

unsigned char pdata bufRxd[40]; //串口接收緩沖區(qū)

 

unsigned char regGroup[5];  //Modbus寄存器組,地址為0x00~0x04

 

extern bit flagBuzzOn;

extern void LcdShowStr(unsigned char x, unsigned char y, const unsigned char *str);

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

 

void ConfigUART(unsigned int baud)  //串口配置函數(shù),baud為波特率

{

    RS485_DIR = 0; //RS485設(shè)置為接收方向

    SCON = 0x50;   //配置串口為模式1

    TMOD &= 0x0F;  //清零T1的控制位

    TMOD |= 0x20;  //配置T1為模式2

    TH1 = 256 - (11059200/12/32) / baud;  //計(jì)算T1重載值

    TL1 = TH1;     //初值等于重載值

    ET1 = 0;       //禁止T1中斷

    ES  = 1;       //使能串口中斷

    TR1 = 1;       //啟動(dòng)T1

}

unsigned char UartRead(unsigned char *buf, unsigned char len) //串口數(shù)據(jù)讀取函數(shù),數(shù)據(jù)接收指針buf,讀取數(shù)據(jù)長(zhǎng)度len,返回值為實(shí)際讀取到的數(shù)據(jù)長(zhǎng)度

{

    unsigned char i;

    

    if (len > cntRxd) //讀取長(zhǎng)度大于接收到的數(shù)據(jù)長(zhǎng)度時(shí),

    {

        len = cntRxd; //讀取長(zhǎng)度設(shè)置為實(shí)際接收到的數(shù)據(jù)長(zhǎng)度

    }

    for (i=0; i<len; i++) //拷貝接收到的數(shù)據(jù)

    {

        *buf = bufRxd[i];

        buf++;

    }

    cntRxd = 0;  //清零接收計(jì)數(shù)器

    

    return len;  //返回實(shí)際讀取長(zhǎng)度

}

void DelayX10us(unsigned char t)  //軟件延時(shí)函數(shù),延時(shí)時(shí)間(t*10)us

{

    do {

        _nop_();

        _nop_();

        _nop_();

        _nop_();

        _nop_();

        _nop_();

        _nop_();

        _nop_();

    } while (--t);

}

void UartWrite(unsigned char *buf, unsigned char len) //串口數(shù)據(jù)寫(xiě)入函數(shù),即串口發(fā)送函數(shù),待發(fā)送數(shù)據(jù)指針buf,數(shù)據(jù)長(zhǎng)度len

{

    RS485_DIR = 1;  //RS485設(shè)置為發(fā)送

    while (len--)   //發(fā)送數(shù)據(jù)

    {

        flagOnceTxd = 0;

        SBUF = *buf;

        buf++;

        while (!flagOnceTxd);

    }

    DelayX10us(5);  //等待最后的停止位完成,延時(shí)時(shí)間由波特率決定

    RS485_DIR = 0;  //RS485設(shè)置為接收

}

 

void UartDriver() //串口驅(qū)動(dòng)函數(shù),檢測(cè)接收到的命令并執(zhí)行相應(yīng)動(dòng)作

{

    unsigned char i;

    unsigned char cnt;

    unsigned char len;

    unsigned char buf[30];

    unsigned char str[4];

    unsigned int  crc;

    unsigned char crch, crcl;

 

    if (cmdArrived) //有命令到達(dá)時(shí),讀取處理該命令

    {

        cmdArrived = 0;

        len = UartRead(buf, sizeof(buf)); //將接收到的命令讀取到緩沖區(qū)中

        if (buf[0] == 0x01)  //核對(duì)地址以決定是否響應(yīng)命令,本例本機(jī)地址為0x01

        {

            crc = GetCRC16(buf, len-2); //計(jì)算CRC校驗(yàn)值

            crch = crc >> 8;

            crcl = crc & 0xFF;

            if ((buf[len-2] == crch) && (buf[len-1] == crcl)) //判斷CRC校驗(yàn)是否正確

            {

                switch (buf[1]) //按功能碼執(zhí)行操作

                {

                    case 0x03:  //讀取一個(gè)或連續(xù)的寄存器

                        if ((buf[2] == 0x00) && (buf[3] <= 0x05)) //寄存器地址支持0x0000~0x0005

                        {

                            if (buf[3] <= 0x04)

                            {

                                i = buf[3];      //提取寄存器地址

                                cnt = buf[5];    //提取待讀取的寄存器數(shù)量

                                buf[2] = cnt*2;  //讀取數(shù)據(jù)的字節(jié)數(shù),為寄存器數(shù)*2,因Modbus定義的寄存器為16位

                                len = 3;

                                while (cnt--)

                                {

                                    buf[len++] = 0x00;      //寄存器高字節(jié)補(bǔ)0

                                    buf[len++] = regGroup[i++]; //低字節(jié)

                                }

                            }

                            else  //地址0x05為蜂鳴器狀態(tài)

                            {

                                buf[2] = 2;  //讀取數(shù)據(jù)的字節(jié)數(shù)

                                buf[3] = 0x00;

                                buf[4] = flagBuzzOn;

                                len = 5;

                            }

                            break;

                        }

                        else  //寄存器地址不被支持時(shí),返回錯(cuò)誤碼

                        {

                            buf[1] = 0x83;  //功能碼最高位置1

                            buf[2] = 0x02;  //設(shè)置異常碼為02-無(wú)效地址

                            len = 3;

                            break;

                        }

                        

                    case 0x06:  //寫(xiě)入單個(gè)寄存器

                        if ((buf[2] == 0x00) && (buf[3] <= 0x05)) //寄存器地址支持0x0000~0x0005

                        {

                            if (buf[3] <= 0x04)

                            {

                                i = buf[3];             //提取寄存器地址

                                regGroup[i] = buf[5];   //保存寄存器數(shù)據(jù)

                                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為蜂鳴器狀態(tài)

                            {

                                flagBuzzOn = (bit)buf[5]; //寄存器值轉(zhuǎn)換為蜂鳴器的開(kāi)關(guān)

                            }

                            len -= 2; //長(zhǎng)度-2以重新計(jì)算CRC并返回原幀

                            break;

                        }

                        else  //寄存器地址不被支持時(shí),返回錯(cuò)誤碼

                        {

                            buf[1] = 0x86;  //功能碼最高位置1

                            buf[2] = 0x02;  //設(shè)置異常碼為02-無(wú)效地址

                            len = 3;

                            break;

                        }

                        

                    default:  //其它不支持的功能碼

                        buf[1] |= 0x80;  //功能碼最高位置1

                        buf[2] = 0x01;   //設(shè)置異常碼為01-無(wú)效功能

                        len = 3;

                        break;

                }

                crc = GetCRC16(buf, len); //計(jì)算CRC校驗(yàn)值

                buf[len++] = crc >> 8;    //CRC高字節(jié)

                buf[len++] = crc & 0xFF;  //CRC低字節(jié)

                UartWrite(buf, len);      //發(fā)送響應(yīng)幀

            }

        }

    }

}

 

void UartRxMonitor(unsigned char ms)  //串口接收監(jiān)控函數(shù)

{

    static unsigned char cntbkp = 0;

    static unsigned char idletmr = 0;

 

    if (cntRxd > 0)  //接收計(jì)數(shù)器大于零時(shí),監(jiān)控總線空閑時(shí)間

    {

        if (cntbkp != cntRxd)  //接收計(jì)數(shù)器改變,即剛接收到數(shù)據(jù)時(shí),清零空閑計(jì)時(shí)

        {

            cntbkp = cntRxd;

            idletmr = 0;

        }

        else

        {

            if (idletmr < 5)  //接收計(jì)數(shù)器未改變,即總線空閑時(shí),累積空閑時(shí)間

            {

                idletmr += ms;

                if (idletmr >= 5)  //空閑時(shí)間超過(guò)4個(gè)字節(jié)傳輸時(shí)間即認(rèn)為一幀命令接收完畢

                {

                    cmdArrived = 1; //設(shè)置命令到達(dá)標(biāo)志

                }

            }

        }

    }

    else

    {

        cntbkp = 0;

    }

}

void InterruptUART() interrupt 4  //UART中斷服務(wù)函數(shù)

{

     if (RI)  //接收到字節(jié)

    {

        RI = 0;   //手動(dòng)清零接收中斷標(biāo)志位

        if (cntRxd < sizeof(bufRxd)) //接收緩沖區(qū)尚未用完時(shí),

        {

            bufRxd[cntRxd++] = SBUF; //保存接收字節(jié),并遞增計(jì)數(shù)器

        }

     }

     if (TI)  //字節(jié)發(fā)送完畢

    {

         TI = 0;   //手動(dòng)清零發(fā)送中斷標(biāo)志位

        flagOnceTxd = 1;  //設(shè)置單次發(fā)送完成標(biāo)志

    }

}

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

#include <reg52.h>

 

#define LCD1602_DB   P0

 

sbit LCD1602_RS = P1^0;

sbit LCD1602_RW = P1^1;

sbit LCD1602_E  = P1^5;

 

void LcdWaitReady()  //等待液晶準(zhǔn)備好

{

    unsigned char sta;

    

    LCD1602_DB = 0xFF;

    LCD1602_RS = 0;

    LCD1602_RW = 1;

    do

    {

        LCD1602_E = 1;

        sta = LCD1602_DB; //讀取狀態(tài)字

        LCD1602_E = 0;

    } while (sta & 0x80); //bit7等于1表示液晶正忙,重復(fù)檢測(cè)直到其等于0為止

}

void LcdWriteCmd(unsigned char cmd)  //寫(xiě)入命令函數(shù)

{

    LcdWaitReady();

    LCD1602_RS = 0;

    LCD1602_RW = 0;

    LCD1602_DB = cmd;

    LCD1602_E  = 1;

    LCD1602_E  = 0;

}

void LcdWriteDat(unsigned char dat)  //寫(xiě)入數(shù)據(jù)函數(shù)

{

    LcdWaitReady();

    LCD1602_RS = 1;

    LCD1602_RW = 0;

    LCD1602_DB = dat;

    LCD1602_E  = 1;

    LCD1602_E  = 0;

}

void LcdShowStr(unsigned char x, unsigned char y, const unsigned char *str)  //顯示字符串,屏幕起始坐標(biāo)(x,y),字符串指針str

{

    unsigned char addr;

    

    //由輸入的顯示坐標(biāo)計(jì)算顯示RAM的地址

    if (y == 0)

        addr = 0x00 + x; //第一行字符地址從0x00起始

    else

        addr = 0x40 + x; //第二行字符地址從0x40起始

    

    //由起始顯示RAM地址連續(xù)寫(xiě)入字符串

    LcdWriteCmd(addr | 0x80); //寫(xiě)入起始地址

    while (*str != '\0')      //連續(xù)寫(xiě)入字符串?dāng)?shù)據(jù),直到檢測(cè)到結(jié)束符

    {

        LcdWriteDat(*str);

        str++;

    }

}

void LcdInit()  //液晶初始化函數(shù)

{

    LcdWriteCmd(0x38);  //16*2顯示,5*7點(diǎn)陣,8位數(shù)據(jù)接口

    LcdWriteCmd(0x0C);  //顯示器開(kāi),光標(biāo)關(guān)閉

    LcdWriteCmd(0x06);  //文字不動(dòng),地址自動(dòng)+1

    LcdWriteCmd(0x01);  //清屏

}

   關(guān)于CRC校驗(yàn)的算法,如果不是專(zhuān)門(mén)學(xué)習(xí)校驗(yàn)算法本身,大家可以不去研究這個(gè)程序的細(xì)節(jié),文檔直接給我們提供了函數(shù),我們直接調(diào)用即可。 

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

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

    unsigned int index;

    unsigned char crch = 0xFF;  //高CRC字節(jié)

    unsigned char crcl = 0xFF;  //低CRC字節(jié)

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

        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低位字節(jié)值表

        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--)  //計(jì)算指定長(zhǎng)度的CRC

    {

        index = crch ^ *ptr++;

        crch = crcl ^ TabH[index];

        crcl = TabL[index];

    }

    

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

}                           

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

void ConfigTimer0(unsigned int ms);

extern void LcdInit();

extern void ConfigUART(unsigned int baud);

extern void UartRxMonitor(unsigned char ms);

extern void UartDriver();

 

void main ()

{

    EA = 1;           //開(kāi)總中斷

    ConfigTimer0(1);  //配置T0定時(shí)1ms

    ConfigUART(9600); //配置波特率為9600

    LcdInit();        //初始化液晶

    

    while(1)

    {

        UartDriver();

    }

}

 

void ConfigTimer0(unsigned int ms)  //T0配置函數(shù)

{

    unsigned long tmp;

    

    tmp = 11059200 / 12;      //定時(shí)器計(jì)數(shù)頻率

    tmp = (tmp * ms) / 1000;  //計(jì)算所需的計(jì)數(shù)值

    tmp = 65536 - tmp;        //計(jì)算定時(shí)器重載值

    tmp = tmp + 34;           //修正中斷響應(yīng)延時(shí)造成的誤差

    

    T0RH = (unsigned char)(tmp >> 8);  //定時(shí)器重載值拆分為高低字節(jié)

    T0RL = (unsigned char)tmp;

    TMOD &= 0xF0;   //清零T0的控制位

    TMOD |= 0x01;   //配置T0為模式1

    TH0 = T0RH;     //加載T0重載值

    TL0 = T0RL;

    ET0 = 1;        //使能T0中斷

    TR0 = 1;        //啟動(dòng)T0

}

void InterruptTimer0() interrupt 1  //T0中斷服務(wù)函數(shù)

{

    TH0 = T0RH;  //定時(shí)器重新加載重載值

    TL0 = T0RL;

    if (flagBuzzOn)  //蜂鳴器鳴叫或關(guān)閉

        BUZZ = ~BUZZ;

    else

        BUZZ = 1;

    UartRxMonitor(1);  //串口接收監(jiān)控

}

編輯:admin  最后修改時(shí)間:2018-05-08

聯(lián)系方式

0755-82591179

傳真:0755-82591176

郵箱:vicky@yingtexin.net

地址:深圳市龍華區(qū)民治街道民治大道973萬(wàn)眾潤(rùn)豐創(chuàng)業(yè)園A棟2樓A08

Copyright © 2014-2023 穎特新科技有限公司 All Rights Reserved.  粵ICP備14043402號(hào)-4

韩国日本欧美国产三级| 国产日韩精品欧美综合区| 一级欧美一级欧美在线播| 91人人妻人人爽人人狠狠| 噜噜中文字幕一区二区| 成人区人妻精品一区二区三区| 亚洲综合色婷婷七月丁香| 久久精品国产99国产免费| 国产一区二区不卡在线视频| 日本高清视频在线观看不卡| 出差被公高潮久久中文字幕| 日韩欧美国产精品自拍| 国产精品福利一级久久| 免费一级欧美大片免费看| 男女午夜福利院在线观看 | 色婷婷国产精品视频一区二区保健 | 欧美偷拍一区二区三区四区| 久久综合狠狠综合久久综合| 亚洲天堂国产精品久久精品| 亚洲高清欧美中文字幕| 日韩精品日韩激情日韩综合| 日韩精品你懂的在线观看| 沐浴偷拍一区二区视频| 亚洲天堂精品1024| 国产丝袜女优一区二区三区| 日本加勒比不卡二三四区| 国产成人精品一区二区三区| 丝袜美女诱惑在线观看| 中文字幕欧美精品人妻一区| 一二区不卡不卡在线观看| 一区二区三区亚洲国产| 国产女性精品一区二区三区| 色婷婷中文字幕在线视频| 亚洲精品中文字幕欧美| 国产又大又黄又粗的黄色| 一区二区三区日韩经典| 国产高清在线不卡一区| 少妇人妻中出中文字幕| 久久老熟女一区二区三区福利| 精品国产亚洲av成人一区| 日本高清加勒比免费在线|