85|0

1125

帖子

0

资源

纯净的硅(中级)

分享基于MSP430的MODBUS实例 [复制链接]

这是tsg9456原作者在实际应用中的源程序,希望能帮到大家
运行代码 复制代码
 
#include "synth.h" 
//------------------------------------------------------------------------------ 
bool CommState;             // 通讯状态 
bool  Request;              // 允许接收 
bool  Response;             // 允许发送 
bool  EnCommWrite;          // 允许通讯写 
uchar UDRBuf;               // 通讯接收寄存器缓存 
uchar CommIndex;            // 通讯索引 
uchar CrcLow;               // CRC低字节 
uchar CrcHigh;              // CRC高字节 
uchar Interval;             // 3.5字符时间间隔 
uchar CommWrEntry;          // 通讯写入口 
uchar CommBuf[BUF_SIZE];    // 通讯缓冲区 
uint  StartAddr;            // 起始地址 
uint RegNum;                // 寄存器数量 
int bAudBuf;                // 通讯波特率缓存 
int FormBuf;                // 通讯数据格式缓存 
 
extern const StrKeybd Keybd[]; 
 
//------------------------------------------------------------------------------ 
void ResetInterval(void)    // 重置3.5字符时间间隔 

    switch(bAudBuf)       
    {                   
        case  0: Interval = (uchar)(1000/( 1200/11.0)*3.5/TBASE); break; 
        case  1: Interval = (uchar)(1000/( 2400/11.0)*3.5/TBASE); break; 
        case  2: Interval = (uchar)(1000/( 4800/11.0)*3.5/TBASE); break; 
        default: Interval = (uchar)(1000/( 9600/11.0)*3.5/TBASE); break; 
        case  4: Interval = (uchar)(1000/(19200/11.0)*3.5/TBASE); break;       
    } 

 
//****************************************************************************** 
void OpenComm(void)    // 打开或关闭通讯 

    ResetInterval(); 
    UCA0CTL1 |= (UCSSEL_2 + UCRXEIE); 
    switch(FormBuf) 
    { 
        default: UCA0CTL0 = UCSPB;         break;  // N-2 
        case  1: UCA0CTL0 = UCPEN;         break;  // O-1 
        case  2: UCA0CTL0 = UCPEN + UCPAR; break;  // E-1 
        case  3: UCA0CTL0 = 0;             break;  // N-1 
    } 
    switch(bAudBuf) 
    { 
        case  0: UCA0BR1 = (uint)(BRCLK/1200) >> 8; 
                 UCA0BR0 = (uchar)((uint)(BRCLK/1200)); 
                 UCA0MCTL = (uint)((BRCLK/1200-(uint)(BRCLK/1200))*8)<<1; 
                 break; 
        case  1: UCA0BR1 = (uint)(BRCLK/2400) >> 8; 
                 UCA0BR0 = (uchar)((uint)(BRCLK/2400)); 
                 UCA0MCTL = (uint)((BRCLK/2400-(uint)(BRCLK/2400))*8)<<1; 
                 break; 
        case  2: UCA0BR1 = (uint)(BRCLK/4800) >> 8; 
                 UCA0BR0 = (uchar)((uint)(BRCLK/4800)); 
                 UCA0MCTL = (uint)((BRCLK/4800-(uint)(BRCLK/4800))*8)<<1; 
                 break; 
        default: UCA0BR1 = (uint)(BRCLK/9600) >> 8; 
                 UCA0BR0 = (uchar)((uint)(BRCLK/9600)); 
                 UCA0MCTL = (uint)((BRCLK/9600-(uint)(BRCLK/9600))*8)<<1; 
                 break; 
        case  4: UCA0BR1 = (uint)(BRCLK/19200) >> 8; 
                 UCA0BR0 = (uchar)((uint)(BRCLK/19200)); 
                 UCA0MCTL = (uint)((BRCLK/19200-(uint)(BRCLK/19200))*8)<<1; 
                 break; 
    } 
    UCA0CTL1 &= ~UCSWRST; 
    IE2 |= UCA0RXIE; 

 
//****************************************************************************** 
void Communication(void)    // 通讯 

    if((SMM.out1 == COMM) || (SMM.out2 == COMM) || (SMM.out3 == COMM)) 
    { 
        if((bAudBuf != SMM.bAud) || (FormBuf != SMM.ForM) || (!CommState)) 
        { 
            bAudBuf = SMM.bAud; 
            FormBuf = SMM.ForM; 
            UCA0CTL1 = UCSWRST; 
            OpenComm(); 
            CommState = true; 
        } 
    } 
    else 
    { 
        UCA0CTL1 = UCSWRST; 
        CommState = false; 
    } 

 
//****************************************************************************** 
void SingleCRC(uchar data)    // 计算单字节CRC校验码 
{       
    uchar c = CrcLow ^ data; 
    CrcLow  = TabCRC[c] ^ CrcHigh; 
    CrcHigh = TabCRC[c + 0x100]; 

 
//****************************************************************************** 
__monitor void SilentInterval(void)   // 检测通讯3.5字符时间间隔 

    if(CommState) 
    { 
        if(Interval == 0)                   
        { 
            ResetInterval(); 
            CrcLow = 0xFF; 
            CrcHigh = 0xFF; 
            CommIndex = 0; 
            if(Response) 
            { 
                Response = false; 
                IE2 |= UCA0TXIE; 
            } 
            else 
            { 
                IE2 &= ~UCA0TXIE; 
                Request = true; 
            } 
        } 
        else 
            --Interval; 
    } 

 
//****************************************************************************** 
bool CheckDataValid(void)    // 检测写入数据的有效性 

    uchar c, index = StartAddr + OFFSET; 
    for(c = 0; c < RegNum; ++c, ++index) 
    { 
        uchar buf = c * 2; 
        int data = ((int)CommBuf[7 + buf] << 8) | CommBuf[8 + buf];       
        if((data < Keybd[index].LowerLimit) || (data > Keybd[index].HigherLimit))       
            return(false);                   
    } 
    return(true); 

 
//****************************************************************************** 
void GetDataToMenu(void)    // 更新参数值 

    uchar c, *ta = &SB[(StartAddr + OFFSET) * 2], *src = &CommBuf[8]; 
    for(c = RegNum; c; --c) 
    {                       // 低字节 
        *ta = *src; 
        ta  += 2; src += 2; 
    } 
    ta = &SB[(StartAddr + OFFSET) * 2 + 1], src = &CommBuf[7]; 
    for(c = RegNum; c; --c) 
    {                       // 高字节 
        *ta = *src; 
        ta  += 2; src += 2; 
    } 

 
//****************************************************************************** 
void GetDataToBuff(void)    // 取参数值 

    uchar c, *ta = &CommBuf[4], *src = &SB[(StartAddr + OFFSET) * 2]; 
    for(c = RegNum; c; --c) 
    {                       // 低字节 
        *ta = *src; 
        ta  += 2; src += 2; 
    } 
    ta = &CommBuf[3], src = &SB[(StartAddr + OFFSET) * 2 + 1]; 
    for(c = RegNum; c; --c) 
    {                       // 高字节 
        *ta = *src; 
        ta  += 2; src += 2; 
    } 

 
//****************************************************************************** 
void ManageWrite(void)    // 写指令 

    uchar c = REGNUM * 2 + 7;    // 指向CRCL 
    if(CommIndex < c) 
    { 
        SingleCRC(UDRBuf); 
        CommBuf[CommIndex++] = UDRBuf; 
    } 
    else if(CommIndex == c) 
    { 
        if(CrcLow == UDRBuf) 
        { 
            StartAddr = STARTADDR; 
            RegNum = REGNUM; 
            ++CommIndex; 
        } 
        else 
            Request = false; 
    } 
    else 
    { 
        Request = false; 
        if(CrcHigh == UDRBuf) 
        { 
            if((RegNum >= 1) && (RegNum <= 0x7B) && (CommBuf[6] == (RegNum * 2))) 
            { 
                if((StartAddr + RegNum) <= COMM_WL_WR) 
                { 
                    if(!CheckDataValid()) 
                    { 
                        CMD |= 0x80; CommBuf[2] = ERR_DATA;    // 非法数据 
                    } 
                    else 
                    { 
                        GetDataToMenu(); 
                        if(StartAddr < (COMM_WL_WR - 2)) 
                        { 
                            switch(StartAddr+RegNum) 
                            { 
                                case COMM_WL_WR    : RegNum -= 2; break; 
                                case (COMM_WL_WR-1): RegNum -= 1; break; 
                                default            :              break; 
                            } 
                            CommWrEntry = ENTRY;       
                            EnCommWrite = true; 
                        } 
                    } 
                } 
                else 
                { 
                    CMD |= 0x80; CommBuf[2] = ERR_ADDR;    // 非法地址 
                } 
            } 
            else 
            { 
                CMD |= 0x80; CommBuf[2] = ERR_NUM;    // 非法数量 
            } 
            Response = true; 
        } 
    } 

 
//****************************************************************************** 
void ManageRead(void)    // 读指令 

    if(CommIndex == 6) 
    { 
        if(CrcLow == UDRBuf) 
        { 
            StartAddr = STARTADDR; 
            RegNum = REGNUM; 
            CommBuf[2] = RegNum * 2; 
            ++CommIndex; 
        } 
        else 
            Request = false; 
    } 
    else 
    { 
        Request = false; 
        if(CrcHigh == UDRBuf) 
        { 
            if((RegNum >= 1) && (RegNum <= 0x7D)) 
            { 
                if((StartAddr + RegNum) <= COMM_WL_RD) 
                    GetDataToBuff(); 
                else 
                { 
                    CMD |= 0x80; CommBuf[2] = ERR_ADDR;    // 非法地址 
                } 
            } 
            else 
            { 
                CMD |= 0x80; CommBuf[2] = ERR_NUM;    // 非法数量 
            } 
            Response = true; 
        } 
    } 

 
//****************************************************************************** 
#pragma vector = USCIAB0TX_VECTOR 
__interrupt void UART_transmit(void)    // 通讯发送 

    uchar c; 
    TACCTL0 &= ~CCIE; 
    IE2 &= ~UCA0TXIE; 
    __enable_interrupt(); 
    ResetInterval(); 
    if(CMD == READ)                     // 读指令 
        c = CommBuf[2] + 3;             // 指向CRCL 
    else if(CMD == WRITE)               // 写指令 
        c = 6; 
    else                                // 错误的指令 
        c = 3; 
    if(CommIndex <= (c + 1)) 
    {       
        if(CommIndex < c)                                                       
        { 
            c = CommBuf[CommIndex]; 
            SingleCRC(c); 
            UCA0TXBUF = c; 
        } 
        else if(CommIndex == c) 
            UCA0TXBUF = CrcLow; 
        else 
            UCA0TXBUF = CrcHigh; 
        ++CommIndex; 
        __disable_interrupt(); 
        IE2 |= UCA0TXIE; 
        TACCTL0 |= CCIE; 
    } 
    else 
    { 
        __disable_interrupt(); 
        TACCTL0 |= CCIE; 
    } 

 
//****************************************************************************** 
#pragma vector = USCIAB0RX_VECTOR 
__interrupt void UART_receive(void)    // 通讯接收 

    UDRBuf = UCA0RXBUF; 
    TACCTL0 &= ~CCIE; 
    IE2 &= ~UCA0RXIE; 
    __enable_interrupt(); 
    ResetInterval(); 
    if(Request) 
    { 
        switch(CommIndex) 
        { 
            case  0: if(UDRBuf != SMM.Addr) 
                     { 
                         Request = false; 
                         break; 
                     } 
            case  1: 
            case  2: 
            case  3: 
            case  4: 
            case  5: SingleCRC(UDRBuf); 
                     CommBuf[CommIndex++] = UDRBuf; 
                     break; 
            default: if(CMD == READ)           // 读指令 
                         ManageRead(); 
                     else if(CMD == WRITE)     // 写指令 
                         ManageWrite(); 
                     else                      // 非法指令 
                     { 
                         Request = false; 
                         CMD |= 0x80; CommBuf[2] = ERR_CMD; 
                         Response = true; 
                     } 
                     break; 
        } 
    } 
    __disable_interrupt(); 
    IE2 |= UCA0RXIE; 
    TACCTL0 |= CCIE; 

欢迎发贴分享设计心得、开源DIY...
tsg9456    
2009-09-24 13:36:27 引用 只看此人 评帖
2楼
头像级别
关注Ta给tsg9456发消息
MCP33:微控3.3V/1uA超低功耗LDO现货供应
说明一下:
仪表有一个2ms的系统时钟,每2ms将3.5字符时间-1,如果字符时间已减为0,将通讯资源重置,允许新的接收或发送开始,通讯写只是建立了写使能标志和缓存了写操作用到的资源,具体的应用是检测到写入标志就执行写入(可以在主程序或系统时钟中断中写入),删除部分冗余的指令即可直接应用于实际的系统

宏定义如下:

//------------------------------------------------------------------------------

#define ERR_CMD    0x01             // 非法指令
#define ERR_ADDR   0x02             // 非法地址
#define ERR_NUM    0x03             // 非法数量
#define ERR_DATA   0x04        // 非法数据

#define READ       0x03             // 读
#define WRITE      0x10             // 写
#define CMD        CommBuf[1]  // 指令

#define STARTADDR  (((uint)CommBuf[2]<<8)|CommBuf[3])    // 起始地址
#define REGNUM     (((uint)CommBuf[4]<<8)|CommBuf[5])    // 寄存器数量

//------------------------------------------------------------------------------

const uchar TabCRC[] =                                    
{
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
    0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
    0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
    0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
    0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
    0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
    0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
    0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
    0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
    0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
    0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
    0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
    0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
    0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
    0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
    0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
    0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
    0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
    0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
    0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
    0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
    0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
    0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
    0x43, 0x83, 0x41, 0x81, 0x80, 0x40
};

#endif

typedef struct
{
    uchar StateTable[4][2];    // 状态表
    uchar code[4];             // 参数代号
    uchar address;             // 参数地址
    uchar decimal;             // 小数点位置
    int LowerLimit;            // 下限
    int HigherLimit;           // 上限
    int initial;               // 初值
    const uchar *pointer;      // 参数值转换为字符的指针(用于参数值显示为字符)
}StrKeybd;

const StrKeybd Keybd[] =
{
内容根据StrKeybd结构填入即可。
};

//------------------------------------------------------------------------------

typedef struct
{

}StrMenu;

typedef struct
{
}StrParm;

//------------------------------------------------------------------------------

typedef struct
{
    StrMenu Menu;
    StrParm Parm;
}StrSynth;

typedef union
{
    uchar Byte[sizeof(StrSynth)];
    uint  Word[sizeof(StrSynth)/2];
    StrSynth Member;
}UniSynth;

UniSynth Synth;
运行代码 复制代码


#define SB  Synth.Byte
#define SW  Synth.Word
#define SMM Synth.Member.Menu
#define SMP Synth.Member.Parm

#endif


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

最新文章 更多>>
    关闭
    站长推荐上一条 1/5 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2021 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表