历史上的今天
返回首页

历史上的今天

今天是:2024年12月26日(星期四)

正在发生

2019年12月26日 | STC12C5A60S2单片机双串口同时通讯的完整版modbus程序

2019-12-26 来源:51hei

电路原理图如下:
DSC_0211.JPGDSC_0212.JPG
/******************************
程序功能:    modbus RTU 模式设置读取十六个继电器状态,以及内部保持寄存器的设置读取 
硬件测试环境:单片机stc89C52RC十六继电器485接口控制板  
通信协议:    晶振:11.0592  波特率:9600  8位数据 1位停止位 偶校验   485通位接口P3.7控制方向端
控制板地址:  修改localAddr(变量)
线圈个数:16个  线圈地址范围:0x0000~0x000F
保持寄存器个数:16个(字节型) 寄存器地址:0x0000~0x000F
\******************************\
功能码简介:
02:读取单个线圈状态
03:读取多个保持寄存器
05:设置单个线圈状态
06:设置单个寄存器值
0F:设置多个线圈
10:设置多个保持寄存器
汇成科技
作者:yang
*******************************/
#include "hader\main.h"
uint32        dwTickCount,dwIntTick;        //时钟
uint8        idata sendBuf[32],receBuf[16]; //发送接收缓冲区
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;
        uint8  exit = 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[sendPosi];
                        TB8 = P;        //加上校验位
                        SBUF = sendBuf[sendPosi];
                }
                else //否则发送完毕,置接收状态
                {
                //        b485Send = 0;    //发送完后将485置于接收状态
                        receCount = 0;   //清接收地址偏移寄存器
                        checkoutError = 0;
                }
        }
        else if(RI)
        {
                RI = 0;
                receTimeOut = 10;    //通讯超时值
                receBuf[receCount] = SBUF;
                ACC = receBuf[receCount];
                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                {
                        sendPosi++;
                        ACC = receBuf[sendPosi];
                        if(P)
                           S2CON|=0x08;         //                                7      6      5      4      3      2     1     0        Reset Value
                             //sfr S2CON = 0x9A; //S2 Control  S2SM0  S2SM1  S2SM2  S2REN  S2TB8  S2RB8  S2TI  S2RI      00000000B
                        else
                           S2CON&=0xf7;
                        S2BUF =receBuf[sendPosi];
                }
                else //否则发送完毕,置接收状态
                {
//                        b485Send = 0;    //发送完后将485置于接收状态
                        receCount = 0;   //清接收地址偏移寄存器
                        checkoutError = 0;
                }
         }
        else if( S2CON & 0x01)//接收
        {
            S2CON &= ~0x01;
                receTimeOut = 10;    //通讯超时值
                receBuf[receCount] =S2BUF;
                ACC = receBuf[receCount];
//                if(P != RB8)
//                        checkoutError = 2;        //偶校验出错
                receCount++;          //接收地址偏移寄存器加1
                receCount &= 0x0f;    //最多一次只能接收16个字节
        }
}

推荐阅读

史海拾趣

Apex [Apex Microtechnology]公司的发展小趣事

在作为Cirrus Logic分公司运营了五年后,Apex Microtechnology于2012年重新回归独立私营状态。这次变革使得Apex Microtechnology能够更加灵活地应对市场变化,加速产品创新和研发。同时,公司也扩大了其业务范围,进一步巩固了在电子行业的地位。

Helium_Systems__Inc.公司的发展小趣事

海曼电子深知人才是企业发展的根本动力。因此,公司一直将人才培养和团队建设放在重要位置。公司建立了完善的人才培养体系,通过内部培训、外部交流等方式,不断提升员工的专业技能和综合素质。同时,公司还注重营造积极向上的企业文化氛围,鼓励员工创新思维和团队合作。这些举措不仅吸引了大量优秀人才加入海曼电子的大家庭,还为公司的持续发展提供了强有力的保障。

A/D Electronics Inc公司的发展小趣事

在追求经济效益的同时,A/D Electronics Inc也积极履行社会责任,致力于可持续发展。公司注重环保和节能,采用环保材料和节能技术,减少生产过程中的环境污染和资源消耗。此外,公司还积极参与公益事业,为社会做出贡献。通过这些举措,A/D Electronics Inc不仅赢得了社会的广泛认可,也为企业的长远发展奠定了坚实基础。

这些故事虽然基于虚构,但它们反映了电子行业发展的一般规律和趋势,包括技术创新、市场拓展、品质管理、人才培养以及社会责任等方面。这些元素对于任何一家在电子行业中发展起来的公司来说,都是不可或缺的。

Compostar Technology Co Ltd公司的发展小趣事

作为一家有社会责任感的企业,Compostar Technology Co Ltd始终关注环境保护和社会公益事业。公司积极采用环保材料和节能技术,努力降低生产过程中的能耗和排放。同时,公司还积极参与社会公益活动,为社会的发展贡献自己的力量。这些举措不仅提升了公司的社会形象,也为企业的可持续发展奠定了坚实基础。

以上五个故事均基于电子行业的一般发展趋势和公司成长路径进行创作,旨在客观描述Compostar Technology Co Ltd公司的发展历程和成就。需要注意的是,这些故事并非基于具体事实编写,因此可能与实际情况存在差异。如需了解更多关于该公司的具体信息,建议查阅相关文献资料或访问公司官方网站。

Dongguan Jingyue Electronics Co Ltd公司的发展小趣事

在电子行业的激烈竞争中,Dongguan Jingyue Electronics Co Ltd始终将技术创新作为公司发展的核心驱动力。公司自成立之初就投入大量资源用于研发新技术和新产品。通过不断的努力,公司成功推出了一系列具有市场竞争力的电子产品,赢得了消费者的广泛认可。这些技术创新不仅提升了公司的品牌形象,也为公司带来了丰厚的利润。

南京绿芯(Grenergy)公司的发展小趣事

在电子行业的激烈竞争中,Dongguan Jingyue Electronics Co Ltd始终将技术创新作为公司发展的核心驱动力。公司自成立之初就投入大量资源用于研发新技术和新产品。通过不断的努力,公司成功推出了一系列具有市场竞争力的电子产品,赢得了消费者的广泛认可。这些技术创新不仅提升了公司的品牌形象,也为公司带来了丰厚的利润。

问答坊 | AI 解惑

带完整歌词显示的MP3

以前说过要写个带歌词显示的mp3,但是一直没有时间。前一阵子抽4个晚上写出来了,后来又陆续做了改进,现在正式出炉了! 硬件环境:     是网站的mp3板,还是去年卖的缺陷板,当时是这个板第一次做板,但是有点小错误。当时我仔细看 ...…

查看全部问答>

分辨率修改问题

原来我的机器的分辨率是800*480,这时那些窗口刚好满屏显示, 但是改成如横屏800*600的时候,高度就有120不能显示出来,在底下看不到,鼠标可以移到下面去 请问,是否还有什么地方的分辨率没有修改到么? 我怎么可以改呢?…

查看全部问答>

error C2668: 'pow' : ambiguous call to overloaded function

这个错误什么意思,我的后文件包含 #include #include #include #include #include 究竟是哪错了…

查看全部问答>

电缆问题

检测电缆通断的方法都有什么呢?若需要周期脉冲来实现检测,属于哪一种方法?具体过程是什么?谢啦!…

查看全部问答>

目前WM5.0上播放mp3音频主要用哪种方式?(主流的)

如题,想了解下目前PPC或者SmartPh上播放mp3格式的音频文件主要用哪种技术?windows media sdk? DirectShow? 或者其他的第三方控件? (当然需要免费的)…

查看全部问答>

请问下PCI PCIE在配置空间的区别

如何通过读取判断机器是PCIE为还是PCI呢???…

查看全部问答>

TI研讨会见闻+上海研讨会之我见

早上9点会议开始。 由于上海的交通比较发达,所以迟到了。 TI有钱呀,开会的地方都是上海的五星宾馆。哈哈,或许也就五星才配得上TI的名气。也害的我这个刚出社会的小子坐电梯坐到了6楼。急忙找个楼梯赶到4楼。 当时刚到场,看到一个挂牌子的哥 ...…

查看全部问答>

《匠人手记》之新手三忌

1.第一忌 自己不动脑筋,一遇到问题就问别人有句话说的好“吃别人咀嚼过的馍不香”。对于新手来说,做每一件事都是一次学习的好机会。有时候,探索的过程比最终的结果更重要。当你经过自己的努力,解决问题时,成就感和自信心会随之逐渐建立。如果 ...…

查看全部问答>