标题:
显控HMI与单片机通讯案例(含单片机底层程序源码)
[打印本页]
作者:
liucongjun
时间:
2018-4-20 09:25
标题:
显控HMI与单片机通讯案例(含单片机底层程序源码)
看到51hei上面有多人需要给大家分享下显控HMI与单片机通讯案例(含单片机底层),显控触摸屏盒51单片机通过MODBUS协议通讯,读写数据和监视位状态,附触摸屏案例和单片机工程源码与快速接线模块。
还附带了单片机MODBUS通信测试.drw文件.
0.jpg
(27.36 KB, 下载次数: 137)
下载附件
2018-4-20 14:58 上传
单片机源程序如下:
/********************************************
samkoon深圳显控自动化技术
**********************************************/
/********文件信息*****************************
名称:main.c
功能:系统执行文件
创建者:徐思*
适用工程:MODBUS RTU SALVE 通信单片机底层案例
***********************************************/
/********************************************************************************
本段程序用于和samkoon触摸屏使用MODBUS RTU协议通信,单片机作为从站,232连接
samkoon MODBUS 主站功能码说明:
1、0x:读写位状态,读时发功能码 01 写时发功能码05;
2、1x:读输入位状态;发功能码 02;
3、3x:读输入寄存器,发功能码 04;
4、4x:读写寄存器,读时发功能码 03,写时发功能码 06,写32位时发功能码 10;
5、3X-D:读两个寄存器 功能码:03;
6、4X-D:写两个寄存器,功能码 10,读32位时读上来的数据和使用4X高低字节刚好相反
7、3x_bit:读输入寄存器的位,发功能码:04;
8、4x_bit:读写寄存器的位,读时发功能码:03,写时发功能码:06;
**********************************************************************************/
/*---如果要在程序使用该程序,请在程序中注明使用了显控公司资料---*/
/*---如果要在文章使用该程序,请在文章中注明使用了显控公司资料---*/
#include"main.h"
u8 Reciver_Buf;
u8 rece_index=0;
u8 idata sendBuf[75]; //定义发送数组,最大允许发送32个字,64个字节
u8 idata receBuf[75]; //定义接收数组,最大允许接收32个字,64个字节写入
u8 *ps=sendBuf;
u8 *pr=receBuf;
u8 comm_END;
u8 comm_time_out;
u8 Reciver_bit=0;
u16 R_ISP_L;
u16 R_ISP_H;
/*初始化函数*/
void init()
{
int i;
TMOD=0X21; //设定定时器1的工作方式为2,及8位初值自动重装的8位定时器,用于产生波特率,T0工作方式1,用于判断通信帧结束
TH1=0XFD; //设置定时器的初值为0xfd,是按照9600的波特率计算出来的数值
TL1=0XFD; //定时器高低位数值一样,方式2下,定时器自动将高位的数值装入低位,所以设定的时间要一致
TH0=(65536-11111)/256; //T0设定为1ms定时器, 用于判断通信帧结束,同时可用于其他的定时作用
TL0=(65536-11111)%256; //T0低位
TR1=1; //启动T1定时器
REN=1; //运行串口接收数据,REN=1允许串口接收,REN=0禁止串口接收数据
SM0=0; //设置串口工作方式为1,即10位异步通信,1起始位,8数据位,1停止位
SM1=1; //同上,REN、SM0、SM1同属于SCON寄存器,但是SCON寄存器允许位寻址
EA=1; //开总中断
ES=1; //开串口中断
ET0=1; //开定时器中断
TR0=1; //启动T0定时器
P1=0xff; //复位所有输出
relay=1;
bee=1;
for(i=0;i<32;i++) //复位所有
{
*(pb+i)=0;
*(pw+i)=0;
inputBit[i]=0;
}
for(i=0;i<32;i++) //读出存在内部E2PROM内的值
{
R_ISP_L=read_ISP(0x2000+i*2); //读出数据低位
R_ISP_H=read_ISP(0x2000+i*2+1); //读出数据高位
*(pw+i)=((R_ISP_H<<8)&0xff00)+(R_ISP_L&0Xff); //组合数据
}
}
/*********************************************************************************
手动调试函数,通过在触摸屏上操作相对应的位来控制单片机的手动输出
相对应的位说明:
0x0: 手动自动切换位,0:自动,1:手动
0x1-0x10;输出口1-10;
***********************************************************************************/
void adj()
{
u8 i,j=0; //j要有初值=0;
for(i=1;i<9;i++)
{
j=(u8)((*(pb+i)&0x01)<<(i-1))+j;
}
P1=~j;
relay=(~(*(pb+9)))&0x01;
bee=(~(*(pb+10)))&0x01;
}
/**********************************************************************************
将数值保存在内部E2PROM中
0x11:在触摸屏上的保存按钮
************************************************************************************/
void saveData()
{
u8 i;
sectorerase(0x2000); //擦除扇区,这边写入的是第一扇区,在擦除是整个扇区被擦除
for(i=0;i<32;i++)
{
write_ISP((0X2000+i*2),(*(pw+i)&0xff)); //保存低8位数据
write_ISP((0x2000+i*2+1),((*(pw+i)>>8)&0xff)); //保存高8位数据
}
*(pb+11)=0; //保存按妞复位
}
/*主函数*/
void main()
{
init(); //执行初始化程序
while(1) //执行运行程序
{
if(*(pb+0)) adj(); //手动调试
if(*(pb+11)) saveData(); //保存数值
}
}
/*串口中断服务*/
void ser() interrupt 4 //串口中断的序号是4
{
RI=0; //产生串口中断时RI被硬件置1,在串口中断服务程序中需要用软件清0;
comm_END=4; //9600的波特率下,等待3.5个字节需要约4ms的时间
Reciver_bit=1; //产生一次中断置一次位
Reciver_Buf=SBUF; //将接收到的数据赋给一个变量;
receBuf[rece_index++]=Reciver_Buf; //将接收到的数据存入接收数组
}
/*T0中断服务程序*/
void comm_stop() interrupt 1
{
u8 i;
TH0=(65536-11111)/256; //重装T0
TL0=(65536-11111)%256; //T0低位
if(Reciver_bit&&comm_END!=0)
comm_END--;
if(comm_END==0)
{
Reciver_bit=0; //帧接收,对标志位清零
if((*(pr+0)==0x01||*(pr+0)==0x00)&&rece_index>=8) //判断是否为本站地址或者是广播地址,有效报文的字节数量最少是8个字节
{
AnalyzeRecieve(); //分析并生成响应报文
if(*(pr+0)==0x01) //广播模式下不用返回
send_comm(); //发送响应报文
}
comm_END=4; //重新赋延时初值
rece_index=0; //数组长度清零
for(i=0;i<75;i++) //清空接收数组
receBuf[i]=0;
Reciver_Buf=0;
}
}
复制代码
/********************************************
samkoon
**********************************************/
/********文件信息*****************************
名称:main.h
功能:本段程序实现数据的E2PROM操作,实现数据断电保持功能
创建者:徐思坤
适用工程:MODBUS RTU SALVE 通信单片机底层案例
***********************************************/
/*---如果要在程序使用该程序,请在程序中注明使用了显控公司资料---*/
/*---如果要在文章使用该程序,请在文章中注明使用了显控公司资料---*/
#include <intrins.h>
#include"main.h"
//#define _nop_() //定义一个空函数
/***************************************************************
* 定义ISP/IAP操作命令,控制寄存器地址:ISP_CMD E5H *
* 1、0x00: 待机命令,ISP无操作; *
* 2、0x01: 对用户的应用程序FLASH区及数据FLASH区字节读 *
* 3、0x02: 对用户的应用程序FLASH区及数据FLASH区字节编程 *
* 4、0x03: 对用户的应用程序FLASH区及数据FLASH区字节擦除 *
***************************************************************/
#define RDCommand 0x01
#define PRGCommand 0x02
#define ERASECommand 0x03
#define waittime 0x01 //定义CPU的等待时间
/*开始ISP寄存器声明*/
sfr ISP_DATA=0xE2; //FLASH数据寄存区
sfr ISP_ADDRH=0xE3; //FLASH高字节地址寄存器
sfr ISP_ADDRL=0xE4; //FLASH低字节地址寄存器
sfr ISP_CMD=0xE5; //FLASH命令寄存器
sfr ISP_TRIG=0xE6; //FLASH命令触发寄存器
sfr ISP_CONTR=0xE7; //ISP/IAP控制寄存器
/*打开ISP/IAP功能*/
void ISP_enable(void)
{
// ISP_CONTR=ISP_CONTR&0X18; //初始化SP/IAP控制寄存器;
ISP_CONTR=waittime; //写入硬件延时,注意这边是“|”运算
ISP_CONTR=ISP_CONTR|0x80; //打开ISPEN,运行写入,注意是“|”运算
}
/*关闭ISP/IAP功能*/
void ISP_disable(void)
{
ISP_CONTR=ISP_CONTR&0x00; //关闭ISPEN,运行写入,注意是“&”运算
ISP_TRIG=0x00; //清空ISP命令控制触发器
ISP_CMD=0x00;
// EA=1; //打开中断
}
/*建立公用触发函数*/
void go_ISP(void)
{
ISP_TRIG=0x46; //触发ISP/IAP命令字节1,(固定)
ISP_TRIG=0xB9; //触发ISP/IAP命令字节2,(固定)
_nop_(); //执行一个空函数
}
/*扇区擦除函数*/
void sectorerase(u16 addr)
{
ISP_ADDRH=(u8)(addr>>8); /*取地址的高位*/
ISP_ADDRL=(u8)(addr&0xff); //地址的低位
// EA=0; //关闭总中断
ISP_enable(); //打开ISP/IAP功能
ISP_CMD=ERASECommand; //从新给ISP命令寄存器赋值,这边赋的是0x03,表示擦除
go_ISP(); //执行触发命令,将擦除命令写入
ISP_disable(); //关闭ISP功能
}
/*写数据函数(单个字节写入)*/
void write_ISP(u16 st_addr,u8 w_data)
{
ISP_DATA=w_data; //将要写入的数据存入ISP FLASH数据寄存区
ISP_ADDRH=(u8)(st_addr>>8); /*取地址的高位*/
ISP_ADDRL=(u8)(st_addr&0xff); //地址的低位
// EA=0; //关闭总中断
ISP_enable(); //打开ISP/IAP功能
ISP_CMD=PRGCommand; //从新给ISP命令寄存器赋值,这边赋的是0x02,表示写入
go_ISP(); //触发写入
ISP_disable(); //关闭ISP功能
}
/*读数据函数(读单个字节)*/
u8 read_ISP(u16 rd_addr)
{
ISP_ADDRH=(u8)(rd_addr>>8); /*取地址的高位*/
ISP_ADDRL=(u8)(rd_addr&0x00ff); //地址的低位
ISP_CMD=ISP_CMD&0xF8; // 清空ISP命令寄存器的第三位
// EA=0; //关闭总中断
ISP_enable(); //打开ISP/IAP功能
ISP_CMD=RDCommand; //从新给ISP命令寄存器赋值,这边赋的是0x01,表示读出
go_ISP(); //触发写入
ISP_disable(); //关闭ISP功能
return (ISP_DATA); //返回读出的数据
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
显控HMI与单片机通讯案例(含单片机底层) (0).rar
(809.72 KB, 下载次数: 431)
2018-4-20 09:25 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
smartphone
时间:
2018-5-19 21:55
谢谢 下载来学习学习
作者:
叶伟哲
时间:
2018-7-1 17:10
你好,我用功能代码1通讯,老是通讯超时,这个怎么办
作者:
叶伟哲
时间:
2018-7-1 17:12
你好,我用功能代码01通讯,老是超时,怎么办了
作者:
huangjianfeng
时间:
2018-8-21 20:01
51单片机接收到01,02,03等会作出响应。那显控触摸屏是在哪里设置发送01,02,03等modbus码??
作者:
DSCX05
时间:
2018-10-22 14:54
还附带了单片机MODBUS通信测试.drw文件
作者:
tangquan2019
时间:
2018-11-19 08:08
什么是特定用户啊 ,为什么我不能下载呢,我正在用一块显控屏 和AVr单片机的通信,正好借看下 先谢谢了
作者:
jiajie168
时间:
2018-11-21 08:41
好复杂
作者:
yxr201314
时间:
2018-11-29 20:24
过来学习了
作者:
yxr201314
时间:
2018-11-29 20:26
之前都是威纶通的,显控的modbus地址写不进去,不管从站或主站
各们可以说下是什么问题吗
作者:
p0083
时间:
2018-12-18 09:54
我正在用一块显控屏 和RL78单片机的通信,正好借看下 先谢谢了
作者:
lieyanfeiyang
时间:
2019-3-14 08:29
真好,正好要学习。
作者:
lizhendong
时间:
2019-3-17 19:39
支持支持,多谢
作者:
HHHHP
时间:
2019-5-21 21:38
非常好,支持
作者:
lizhendong
时间:
2019-7-20 00:09
太好了,支持一下,谢谢
作者:
难得糊涂2018
时间:
2019-7-22 21:33
这个链接显控哪一款的触摸屏啊
作者:
细洗席
时间:
2019-8-25 19:58
已下载,谢谢分享。
作者:
osjzbing
时间:
2019-9-2 19:37
一下载,感谢分享
作者:
zcq222
时间:
2019-11-6 15:54
谢谢分享,看看
作者:
难得糊涂2018
时间:
2019-11-7 18:54
怎么修改输出点?有大师请指点下!谢谢
作者:
muxiaoyu240
时间:
2020-4-4 06:29
怎样下载
作者:
wangjjqd
时间:
2022-2-9 16:54
正在学习,很需要这方面的资料,谢谢
作者:
mick32
时间:
2022-4-7 04:42
Hello
What kind of HMI to use
作者:
jinshan
时间:
2022-10-25 23:09
单片机用的啥型号的啊?
作者:
mick32
时间:
2022-11-21 02:12
MCU is C51 modbus code
作者:
tyghbn
时间:
2023-3-20 15:59
很好,这个正想学习
作者:
percy
时间:
2023-10-21 11:56
有没有指定具体需要用哪个型号的单片机?
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1