钰平电子 发表于 2023-7-3 11:01:35

单片机采用 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个字节        }}

神农鼎 发表于 2023-7-3 19:57:26

感谢分享 {:4_196:}

18220866638 发表于 2023-7-5 09:39:44

你好,能不能帮我设计一个STC32G12K128的简单电路,proteus

jwd 发表于 2023-7-5 12:58:56

超越自我 发表于 2023-7-5 09:39
你好,能不能帮我设计一个STC32G12K128的简单电路,proteus

proteus都没有STC32G12K128器件好吧

钰平电子 发表于 2023-7-7 13:52:05

超越自我 发表于 2023-7-5 09:39
你好,能不能帮我设计一个STC32G12K128的简单电路,proteus

proteus 这个没有STC32的仿真模型

houzi8 发表于 2024-6-12 12:22:12

谢谢楼主分享,学习下

神农鼎 发表于 2024-6-12 12:55:49

马上 STC8051U 出来,管脚基本兼容 STC12C5A60S2
页: [1]
查看完整版本: 单片机采用 STC12C5A60S2完整版modbus-RTU程序带(看门狗)232+485通讯源码分享