单片机采用 STC12C5A60S2完整版modbus-RTU程序带(看门狗)232+485通讯源码分享
单片机采用51系列 STC12C5A60S2单片机整个程序源码在附件中。/******************************程序功能: modbus RTU 模式设置读取十六个继电器状态,以及内部保持寄存器的设置读取 硬件测试环境:单片机stc89C52RC十六继电器485接口控制板通信协议: 晶振:11.0592波特率:96008位数据 1位停止位 偶校验 485通位接口P3.7控制方向端控制板地址:修改localAddr(变量)线圈个数:16个线圈地址范围:0x0000~0x000F保持寄存器个数:16个(字节型) 寄存器地址:0x0000~0x000F\\******************************\\功能码简介:02:读取单个线圈状态03:读取多个保持寄存器05:设置单个线圈状态06:设置单个寄存器值0F:设置多个线圈10:设置多个保持寄存器*******************************/#include "hader\\main.h"uint32 dwTickCount,dwIntTick; //时钟uint8 idata sendBuf,receBuf; //发送接收缓冲区uint8 idata checkoutError; // ==2 偶校验错uint8 idata receTimeOut; //接收超时uint8 idata c10ms; //10ms 计时uint8 idata c200ms;bit b1ms,bt1ms,b10ms,bt10ms,b100ms,bt100ms; //定时标志位//定时处理void timeProc(void){ b1ms = 0; if(bt1ms) //如果1ms到 { bt1ms = 0; b1ms = 1; if(receTimeOut>0) //如果接收超时值>0 { receTimeOut--; //接收超时-1(1ms减1次) if(receTimeOut==0 && receCount>0) //判断通讯接收是否超时 { // b485Send = 0; //将485置为接收状态 receCount = 0; //将接收地址偏移寄存器清零 checkoutError = 0; } } }} // void TimerProc(void)//初始化void initInt(void){ SCON = 0xd0; TMOD = 0x21; PCON = 0; TH0 = TIMER_HIGHT; TL0 = TIMER_LOW; TH1=0xfd; TL1 = 0xfd; //波特率 9600
TR0 = 1; TR1=1; ET0 = 1; ES = 1; EA = 1;
//串口2设置 S2CON = 0xd0; //方式1,9位数据,波特率不可变S2TB8 偶校验位 BRT=0XFD; //设置波特率9600 AUXR=0x10; //启动串口1波特率发生器 IP=0x00; //优先级默认 //开串口1中断 IE2=0x01; //开串口2中断 } //初始化void initProg(void){
P4SW|=0x20; //配置P4.5为IO口 P4M0|=0x10; //配置P4.4为IO口 P4M1|=0x10; P0=P1=P2=P3=0xff; P4|=0x30; initInt(); //初始化定时器// b485Send = 0;}//上电时读取上次线圈状态,并设置void forceMultipleCoils1() { uint8 tempAddr; uint8 i,k; uint8 Data; uint8exit = 0; for(k=0;k<4;k++) { switch(k) { case 0:Data=coilreg1; break; case 1:Data=coilreg2; break; case 2:Data=coilreg3; break; case 3:Data=coilreg4; break; } for(i=0;i<8;i++) { if( Data &0x01==1) setCoilVal(tempAddr,0); else setCoilVal(tempAddr,1);
Data=Data>>1; tempAddr++; if(tempAddr >=32) { exit = 1; break; } } if(exit==1) break; } }void main(void){
initProg(); localAddr=EEPROMReadByte(0); //从EERPOM的相对0地址读取数据 coilreg1=EEPROMReadByte(1); coilreg2=EEPROMReadByte(2); coilreg3=EEPROMReadByte(3); coilreg4=EEPROMReadByte(4); forceMultipleCoils1(); if(localAddr>=10) { localAddr=1; EEPROMSectorErase(0); //从EEPROM的相对0地址扇区擦除 EEPROMWriteByte(0,localAddr); EEPROMWriteByte(1,coilreg1); EEPROMWriteByte(2,coilreg2); EEPROMWriteByte(3,coilreg1); EEPROMWriteByte(4,coilreg2); } WDT_CONTR =0x32; //大概284.4ms while(1) { timeProc(); checkComm0Modbus(); }}//定时器0 1ms 中断void timer0IntProc() interrupt 1{ TL0 = TIMER_LOW; TH0 = TIMER_HIGHT; dwIntTick++; bt1ms = 1; c10ms++; c200ms++; if(c10ms >= 10) { c10ms = 0; //20ms计时器清零 bt10ms = 1; WDT_CONTR =0x32; // }} // void Timer0IntProc()// 串行中断1程序void commIntProc() interrupt 4{ if(TI) { TI = 0; if(sendPosi < sendCount) //如果发送位置小于发送计数,那么继续发送 { sendPosi++; ACC = sendBuf; TB8 = P; //加上校验位 SBUF = sendBuf; } else //否则发送完毕,置接收状态 { // b485Send = 0; //发送完后将485置于接收状态 receCount = 0; //清接收地址偏移寄存器 checkoutError = 0; } } else if(RI) { RI = 0; receTimeOut = 10; //通讯超时值 receBuf = SBUF; ACC = receBuf; if(P != RB8) checkoutError = 2; //偶校验出错 receCount++; //接收地址偏移寄存器加1 receCount &= 0x0f; //最多一次只能接收16个字节 }} // void CommIntProc()//串口2中断void uart2_isr()interrupt 8{
if( S2CON & 0x02 ) { S2CON &= ~0x02; if(sendPosi<receCount) //如果发送位置小于发送计数,那么继续发送 { sendPosi++; ACC = receBuf; if(P) S2CON|=0x08; // 7 6 5 4 3 2 1 0 Reset Value //sfr S2CON = 0x9A; //S2 ControlS2SM0S2SM1S2SM2S2RENS2TB8S2RB8S2TIS2RI 00000000B else S2CON&=0xf7; S2BUF =receBuf; } else //否则发送完毕,置接收状态 {// b485Send = 0; //发送完后将485置于接收状态 receCount = 0; //清接收地址偏移寄存器 checkoutError = 0; } } else if( S2CON & 0x01)//接收 { S2CON &= ~0x01; receTimeOut = 10; //通讯超时值 receBuf =S2BUF; ACC = receBuf;// if(P != RB8)// checkoutError = 2; //偶校验出错 receCount++; //接收地址偏移寄存器加1 receCount &= 0x0f; //最多一次只能接收16个字节 }}
感谢分享 {:4_196:}
你好,能不能帮我设计一个STC32G12K128的简单电路,proteus 超越自我 发表于 2023-7-5 09:39
你好,能不能帮我设计一个STC32G12K128的简单电路,proteus
proteus都没有STC32G12K128器件好吧 超越自我 发表于 2023-7-5 09:39
你好,能不能帮我设计一个STC32G12K128的简单电路,proteus
proteus 这个没有STC32的仿真模型 谢谢楼主分享,学习下 马上 STC8051U 出来,管脚基本兼容 STC12C5A60S2
页:
[1]