标题:
基于MODBUS协议的单片机主程序 测试通过
[打印本页]
作者:
dior2017
时间:
2017-4-26 15:46
标题:
基于MODBUS协议的单片机主程序 测试通过
基于MODBUS协议的单片机主程序,测试已通过
0.png
(78.29 KB, 下载次数: 98)
下载附件
2017-4-26 21:53 上传
单片机源程序:
#include"reg51.h"
#include"lcd.h"
#include"address.h"
#include"intrins.h"
#include"crc.h"
#define uint unsigned int
#define uchar unsigned char
uchar code sendbuf[]={0x01,0x03,0x00,0x0b,0x00,0x01,0xf5,0xc8};
//0x01 从站地址,0x03功能码,0x00寄存器地址高位,0x09寄存器地址低位,0x00数据个数高位,0x01数据个数低位,0x54CRC校验码高位,0x08CRC校验码低位
uchar code tab[]={'0','1','2','3','4','5','6','7','8','9'};
uchar code error[]={"error!"};
uchar tem[5],tem1[8];
uchar resvbuf[7];
int i,j;
uchar resvend,temp2;
uint crctemp,temp,temp1;
void convert10(uint dat)
{
uchar i;
tem1[0]='U';
tem1[1]='=';
tem1[7]='V';
tem[0]=dat/10000;
dat=dat%10000;
tem[1]=dat/1000;
dat=dat%1000;
tem[2]=dat/100;
dat=dat%100;
tem[3]=dat/10;
tem[4]=dat%10;
for (i=0;i<5;i++)
{
tem1[i+2]=tab[tem[i]];
}
}
void serial_int() interrupt 4 using 1
{
if(RI)
{
RI=0;
//temp2=SBUF;
resvbuf[j++]=SBUF;
if(j==7)
{
j=0;
resvend=1;
}
}
}
void initserial ()
{
resvend=0;
TMOD=0x20;
PCON=0x00;
SCON=0xd8;
TL1=0xfd;
TH1=0xfd;
TR1=1;
ES=1;
}
void displayout()
{
crctemp=crccheck(resvbuf,5);
temp=resvbuf[5];
temp=temp << 8 | resvbuf[6];
if(temp==crctemp)
{
temp1=0;
temp1 |=resvbuf[3];
temp1= temp1<<8 | resvbuf[4];
convert10(temp1);
printf(tem1,8);
}
else
{
printf(error,16);
}
}
void delay_10us(uchar n)
{
do
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}while(--n);
}
void delay_ms(uint n)
{
do
{
delay_10us(131);
}while(--n);
}
void main()
{
initlcd();
initserial();
EA=1;
while(1)
{
i=0;
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
下载:
modbus主机单片机程序.rar
(35.81 KB, 下载次数: 136)
2017-4-26 15:46 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
lele5211314
时间:
2017-6-17 00:25
实物测试通过了吗
作者:
zhangshanqiao
时间:
2021-1-17 17:39
简单,明了,可惜的是各种判断都省略了,如果用在严谨的的场合,显然是不适用的。
作者:
shenyuqiu
时间:
2021-1-18 08:39
用在严谨场合不形,MODBUS最基本的一串数据接收完成的时间间隔判断都没有
作者:
wsh123456789
时间:
2021-7-25 13:55
大锅,拷贝你得程序,LCD根本不显示
作者:
wsh123456789
时间:
2021-7-25 20:37
为么我的程序,LCD不显示
#include"reg51.h"
#include"address.h"
#include"intrins.h"
#include"crc.h"
#define LCD1602_DB P0
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E = P1^5;
void InitLcd1602();
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
#define uint unsigned int
#define uchar unsigned char
uchar code sendbuf[]={0x01,0x03,0x02,0x00,0x00,0x03,0x04,0x73};
//0x01 从站地址,0x03功能码,0x20寄存器地址高位,0x00寄存器地址低位,0x00数据个数高位,0x03数据个数低位,0x04CRC校验码高位,0x73CRC校验码低位
uchar code tab[]={'0','1','2','3','4','5','6','7','8','9'};
uchar code error[]={"error!"};
uchar tem[5],tem1[8];
uchar resvbuf[10];
int i,j;
uchar resvend,temp2;
uint crctemp,temp,temp1;
void convert10(uint dat)
{
uchar i;
tem1[0]='U';
tem1[1]='=';
tem1[7]='V';
tem[0]=dat/10000;
dat=dat%10000;
tem[1]=dat/1000;
dat=dat%1000;
tem[2]=dat/100;
dat=dat%100;
tem[3]=dat/10;
tem[4]=dat%10;
for (i=0;i<5;i++)
{
tem1[i+2]=tab[tem[i]];
}
}
void serial_int() interrupt 4 using 1
{
if(RI)
{
RI=0;
//temp2=SBUF;
resvbuf[j++]=SBUF;
if(j==7)
{
j=0;
resvend=1;
}
}
}
void initserial ()
{
resvend=0;
TMOD=0x20;
PCON=0x00;
SCON=0xd8;
TL1=0xfd;
TH1=0xfd;
TR1=1;
ES=1;
}
void displayout()
{
crctemp=crccheck(resvbuf,9);
temp=resvbuf[9];
temp=temp << 8 | resvbuf[10];
if(temp==crctemp)
{
temp1=0;
temp1 |=resvbuf[3];
temp1= temp1<<8 | resvbuf[4];
convert10(temp1);
LcdShowStr(0, 1, tem1);
//printf(tem1,8);
}
else
{
LcdShowStr(0, 1,error );
//printf(error,16);
}
}
void delay_10us(uchar n)
{
do
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}while(--n);
}
void delay_ms(uint n)
{
do
{
delay_10us(131);
}while(--n);
}
/* 等待液晶准备好 */
void LcdWaitReady()
{
unsigned char sta;
LCD1602_DB = 0xFF;
LCD1602_RS = 0;
LCD1602_RW = 1;
do {
LCD1602_E = 1;
sta = LCD1602_DB; //读取状态字
LCD1602_E = 0;
} while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止
}
/* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 */
void LcdWriteCmd(unsigned char cmd)
{
LcdWaitReady();
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DB = cmd;
LCD1602_E = 1;
LCD1602_E = 0;
}
/* 向LCD1602液晶写入一字节数据,dat-待写入数据值 */
void LcdWriteDat(unsigned char dat)
{
LcdWaitReady();
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DB = dat;
LCD1602_E = 1;
LCD1602_E = 0;
}
/* 设置显示RAM起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
void LcdSetCursor(unsigned char x, unsigned char y)
{
unsigned char addr;
if (y == 0) //由输入的屏幕坐标计算显示RAM的地址
addr = 0x00 + x; //第一行字符地址从0x00起始
else
addr = 0x40 + x; //第二行字符地址从0x40起始
LcdWriteCmd(addr | 0x80); //设置RAM地址
}
/* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{
LcdSetCursor(x, y); //设置起始地址
while (*str != '\0') //连续写入字符串数据,直到检测到结束符
{
LcdWriteDat(*str++); //先取str指向的数据,然后str自加1
}
}
/* 初始化1602液晶 */
void InitLcd1602()
{
LcdWriteCmd(0x38); //16*2显示,5*7点阵,8位数据接口
LcdWriteCmd(0x0C); //显示器开,光标关闭
LcdWriteCmd(0x06); //文字不动,地址自动+1
LcdWriteCmd(0x01); //清屏
}
void main()
{
InitLcd1602();
initserial();
EA=1;
while(1)
{
i=0;
while(i<8)
{
SBUF=sendbuf[i];
while(!TI);
delay_10us(50);
TI=0;
i++;
}
delay_ms(1000);
if(resvend)
{
resvend=0;
displayout();
}
}
}
作者:
wsh123456789
时间:
2021-7-26 12:30
上面程序有点错误,改了一下。还是不显示
#include"reg51.h"
#include"intrins.h"
#include"crc.h"
#define LCD1602_DB P0
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E = P1^5;
void InitLcd1602();
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
#define uint unsigned int
#define uchar unsigned char
uchar code sendbuf[]={0x01,0x03,0x02,0x00,0x00,0x03,0x04,0x73};
//0x01 从站地址,0x03功能码,0x20寄存器地址高位,0x00寄存器地址低位,0x00数据个数高位,0x03数据个数低位,0x04CRC校验码高位,0x73CRC校验码低位
uchar code tab[]={'0','1','2','3','4','5','6','7','8','9'};
uchar code error[]={"error!"};
uchar tem[5],tem1[9];
uchar resvbuf[11];
int i,j;
uchar resvend,temp2;
uint crctemp,temp,temp1;
void convert10(uint dat)
{
uchar i;
tem1[0]='U';
tem1[1]='=';
tem1[7]='V';
tem1[8]='\0';
tem[0]=dat/10000;
dat=dat%10000;
tem[1]=dat/1000;
dat=dat%1000;
tem[2]=dat/100;
dat=dat%100;
tem[3]=dat/10;
tem[4]=dat%10;
for (i=0;i<5;i++)
{
tem1[i+2]=tab[tem[i]];
}
}
void serial_int() interrupt 4 using 1
{
if(RI)
{
RI=0;
//temp2=SBUF;
resvbuf[j++]=SBUF;
if(j==11)
{
j=0;
resvend=1;
}
}
}
void initserial ()
{
resvend=0;
TMOD=0x20;
PCON=0x00;
SCON=0xd8;
TL1=0xfd;
TH1=0xfd;
TR1=1;
ES=1;
}
void displayout()
{
crctemp=crccheck(resvbuf,9);
temp=resvbuf[9];
temp=temp << 8 | resvbuf[10];
if(temp==crctemp)
{
temp1=0;
temp1 |=resvbuf[3];
temp1= temp1<<8 | resvbuf[4];
convert10(temp1);
LcdShowStr(0, 1, tem1);
//printf(tem1,8);
}
else
{
LcdShowStr(0,1,error);
//printf(error,16);
}
}
void delay_10us(uchar n)
{
do
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}while(--n);
}
void delay_ms(uint n)
{
do
{
delay_10us(131);
}while(--n);
}
/* 等待液晶准备好 */
void LcdWaitReady()
{
unsigned char sta;
LCD1602_DB = 0xFF;
LCD1602_RS = 0;
LCD1602_RW = 1;
do {
LCD1602_E = 1;
sta = LCD1602_DB; //读取状态字
LCD1602_E = 0;
} while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止
}
/* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 */
void LcdWriteCmd(unsigned char cmd)
{
LcdWaitReady();
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DB = cmd;
LCD1602_E = 1;
LCD1602_E = 0;
}
/* 向LCD1602液晶写入一字节数据,dat-待写入数据值 */
void LcdWriteDat(unsigned char dat)
{
LcdWaitReady();
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DB = dat;
LCD1602_E = 1;
LCD1602_E = 0;
}
/* 设置显示RAM起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
void LcdSetCursor(unsigned char x, unsigned char y)
{
unsigned char addr;
if (y == 0) //由输入的屏幕坐标计算显示RAM的地址
addr = 0x00 + x; //第一行字符地址从0x00起始
else
addr = 0x40 + x; //第二行字符地址从0x40起始
LcdWriteCmd(addr | 0x80); //设置RAM地址
}
/* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{
LcdSetCursor(x, y); //设置起始地址
while (*str != '\0') //连续写入字符串数据,直到检测到结束符
{
LcdWriteDat(*str++); //先取str指向的数据,然后str自加1
}
}
/* 初始化1602液晶 */
void InitLcd1602()
{
LcdWriteCmd(0x38); //16*2显示,5*7点阵,8位数据接口
LcdWriteCmd(0x0C); //显示器开,光标关闭
LcdWriteCmd(0x06); //文字不动,地址自动+1
LcdWriteCmd(0x01); //清屏
}
void main()
{
InitLcd1602();
initserial();
EA=1;
while(1)
{
i=0;
while(i<8)
{
SBUF=sendbuf[i];
while(!TI);
delay_10us(50);
TI=0;
i++;
}
delay_ms(1000);
if(resvend)
{
resvend=0;
displayout();
}
}
}
作者:
seco_li
时间:
2021-8-6 21:59
不知道这个程序能不能用,学飞一下
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1