欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標(biāo)題:
基于RS485的Modbus通信示例
[打印本頁(yè)]
作者:
落夢(mèng)傷痕
時(shí)間:
2017-2-18 16:33
標(biāo)題:
基于RS485的Modbus通信示例
#include <reg52.h>
sbit BUZZ = P1^6;
bit flagBuzzOn = 0; //蜂鳴器啟動(dòng)標(biāo)志
unsigned char T0RH = 0; //T0重載值的高字節(jié)
unsigned char T0RL = 0; //T0重載值的低字節(jié)
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; //開(kāi)總中斷
ConfigTimer0(1); //配置T0定時(shí)1ms
ConfigUART(9600); //配置波特率為9600
InitLcd1602(); //初始化液晶
while (1)
{
UartDriver(); //調(diào)用串口驅(qū)動(dòng)
}
}
/* 串口動(dòng)作函數(shù),根據(jù)接收到的命令幀執(zhí)行響應(yīng)的動(dòng)作
buf-接收到的命令幀指針,len-命令幀長(zhǎng)度 */
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) //本例中的本機(jī)地址設(shè)定為0x01,
{ //如數(shù)據(jù)幀中的地址字節(jié)與本機(jī)地址不符,
return; //則直接退出,即丟棄本幀數(shù)據(jù)不做任何處理
}
//地址相符時(shí),再對(duì)本幀數(shù)據(jù)進(jìn)行校驗(yàn)
crc = GetCRC16(buf, len-2); //計(jì)算CRC校驗(yàn)值
crch = crc >> 8;
crcl = crc & 0xFF;
if ((buf[len-2]!=crch) || (buf[len-1]!=crcl))
{
return; //如CRC校驗(yàn)不符時(shí)直接退出
}
//地址和校驗(yàn)字均相符后,解析功能碼,執(zhí)行相關(guān)操作
switch (buf[1])
{
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
len = 3; //幀前部已有地址、功能碼、字節(jié)數(shù)共3個(gè)字節(jié)
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ā)送返回幀
}
/* 配置并啟動(dòng)T0,ms-T0定時(shí)時(shí)間 */
void ConfigTimer0(unsigned int ms)
{
unsigned long tmp; //臨時(shí)變量
tmp = 11059200 / 12; //定時(shí)器計(jì)數(shù)頻率
tmp = (tmp * ms) / 1000; //計(jì)算所需的計(jì)數(shù)值
tmp = 65536 - tmp; //計(jì)算定時(shí)器重載值
tmp = tmp + 33; //補(bǔ)償中斷響應(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
}
/* T0中斷服務(wù)函數(shù),執(zhí)行串口接收監(jiān)控和蜂鳴器驅(qū)動(dòng) */
void InterruptTimer0() interrupt 1
{
TH0 = T0RH; //重新加載重載值
TL0 = T0RL;
if (flagBuzzOn) //執(zhí)行蜂鳴器鳴叫或關(guān)閉
BUZZ = ~BUZZ;
else
BUZZ = 1;
UartRxMonitor(1); //串口接收監(jiān)控
}
作者:
15540241206
時(shí)間:
2018-7-6 16:24
程序有殘缺吧,有些函數(shù)被寫(xiě)出來(lái)了但是沒(méi)有調(diào)用
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1