找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4706|回复: 7
打印 上一主题 下一主题
收起左侧

基于MODBUS协议的单片机主程序 测试通过

  [复制链接]
跳转到指定楼层
楼主
基于MODBUS协议的单片机主程序,测试已通过


单片机源程序:
  1. #include"reg51.h"
  2. #include"lcd.h"
  3. #include"address.h"
  4. #include"intrins.h"
  5. #include"crc.h"

  6. #define uint unsigned int
  7. #define uchar unsigned char

  8. uchar code sendbuf[]={0x01,0x03,0x00,0x0b,0x00,0x01,0xf5,0xc8};          
  9. //0x01 从站地址,0x03功能码,0x00寄存器地址高位,0x09寄存器地址低位,0x00数据个数高位,0x01数据个数低位,0x54CRC校验码高位,0x08CRC校验码低位
  10. uchar code tab[]={'0','1','2','3','4','5','6','7','8','9'};
  11. uchar code error[]={"error!"};
  12. uchar tem[5],tem1[8];
  13. uchar resvbuf[7];
  14. int i,j;
  15. uchar resvend,temp2;
  16. uint crctemp,temp,temp1;

  17. void convert10(uint dat)
  18. {
  19.   uchar i;
  20.   tem1[0]='U';
  21.   tem1[1]='=';
  22.   tem1[7]='V';
  23.   tem[0]=dat/10000;
  24.   dat=dat%10000;
  25.   tem[1]=dat/1000;
  26.   dat=dat%1000;
  27.   tem[2]=dat/100;
  28.   dat=dat%100;
  29.   tem[3]=dat/10;
  30.   tem[4]=dat%10;
  31.   for (i=0;i<5;i++)
  32.   {
  33.     tem1[i+2]=tab[tem[i]];
  34.   }
  35. }

  36. void serial_int() interrupt 4         using 1
  37. {
  38. if(RI)
  39. {
  40.    RI=0;
  41.    //temp2=SBUF;
  42.     resvbuf[j++]=SBUF;  
  43.    if(j==7)
  44.    {
  45.      j=0;
  46.          resvend=1;
  47.    }   
  48. }       
  49. }            

  50. void initserial        ()
  51. {
  52. resvend=0;
  53. TMOD=0x20;
  54. PCON=0x00;
  55. SCON=0xd8;
  56. TL1=0xfd;
  57. TH1=0xfd;
  58. TR1=1;
  59. ES=1;
  60. }

  61. void displayout()
  62. {
  63.    crctemp=crccheck(resvbuf,5);
  64.    temp=resvbuf[5];
  65.    temp=temp << 8 | resvbuf[6];
  66.    if(temp==crctemp)
  67.    {
  68.         temp1=0;
  69.             temp1 |=resvbuf[3];
  70.                 temp1= temp1<<8 | resvbuf[4];
  71.                 convert10(temp1);
  72.                 printf(tem1,8);
  73.     }
  74.   else
  75.    {
  76.       printf(error,16);
  77.    }
  78. }          

  79. void delay_10us(uchar n)
  80. {
  81.    do
  82.    {
  83.      _nop_();
  84.      _nop_();
  85.      _nop_();
  86.      _nop_();
  87.      _nop_();
  88.    }while(--n);
  89. }

  90. void delay_ms(uint n)
  91. {
  92.   do
  93.   {
  94.     delay_10us(131);
  95.    }while(--n);
  96. }


  97. void main()
  98. {
  99. initlcd();
  100. initserial();
  101. EA=1;
  102. while(1)
  103. {
  104.   i=0;


  105. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

下载:
modbus主机单片机程序.rar (35.81 KB, 下载次数: 136)

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏9 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:93224 发表于 2017-6-17 00:25 | 只看该作者
实物测试通过了吗
回复

使用道具 举报

板凳
ID:337808 发表于 2021-1-17 17:39 | 只看该作者
简单,明了,可惜的是各种判断都省略了,如果用在严谨的的场合,显然是不适用的。
回复

使用道具 举报

地板
ID:385637 发表于 2021-1-18 08:39 | 只看该作者
用在严谨场合不形,MODBUS最基本的一串数据接收完成的时间间隔判断都没有
回复

使用道具 举报

5#
ID:929006 发表于 2021-7-25 13:55 | 只看该作者
大锅,拷贝你得程序,LCD根本不显示
回复

使用道具 举报

6#
ID:929006 发表于 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();
  }          
       

  }       
}  
回复

使用道具 举报

7#
ID:929006 发表于 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();
  }          
       

  }       
}  

回复

使用道具 举报

8#
ID:768666 发表于 2021-8-6 21:59 | 只看该作者
不知道这个程序能不能用,学飞一下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表