搜索
bottom↓
回复: 28

发一个老农的通用单片机程序的AVR移槙-ModbusRTU应用

[复制链接]

出0入0汤圆

发表于 2009-3-11 15:56:25 | 显示全部楼层 |阅读模式
#include <inavr.h>
    #include <ioavr.h>
    #include <intrinsics.h>
    #include <pgmspace.h>
    #include <stdbool.h>
    #include <math.h>

    #define DISABLE_INTERRUPT()         __disable_interrupt()
    #define ENABLE_INTERRUPT()          __enable_interrupt()

    struct QueueBuffer{
        unsigned char *aBufferStart;
        unsigned char *aBufferEnd;   
        unsigned char *pIn;            
        unsigned char *pOut;        
        unsigned char mCount;        
    };

    extern void Queue_Init(void);
    extern void Queue_Destory(void);
    extern void Queue_Register(struct QueueBuffer *pQueueBuffer,unsigned char QueueBuffer[],unsigned int mSize);
    extern void Queue_Push( struct QueueBuffer *pQueueBuffer, unsigned char mData );
    extern unsigned char Queue_Pop( struct QueueBuffer *pQueueBuffer );
    extern unsigned char Queue_Read( struct QueueBuffer *pQueueBuffer, unsigned char mId );
    extern unsigned int Queue_Num( struct QueueBuffer *pQueueBuffer );
    extern void Queue_Clear( struct QueueBuffer *pQueueBuffer );


void Queue_Init(void)
{
}

void Queue_Destory(void)
{
}

void Queue_Register(struct QueueBuffer *pQueueBuffer,unsigned char QueueBuffer[],unsigned int mSize)
{
    //struct QueueBuffer *pQueueBuffer;

    //pQueueBuffer = (struct QueueBuffer *)Memory_Malloc(sizeof(struct QueueBuffer));
    //Memory_Memset((unsigned char *)pQueueBuffer,0,sizeof(struct QueueBuffer));

    //pQueueBuffer->aBufferStart = pQueueBuffer->pIn = pQueueBuffer->pOut=Memory_Malloc(mSize);
    //pQueueBuffer->aBufferEnd   = pQueueBuffer->aBufferStart+mSize;

    //return pQueueBuffer;
    pQueueBuffer->aBufferStart = QueueBuffer;
    pQueueBuffer->pIn          = QueueBuffer;
    pQueueBuffer->pOut         = QueueBuffer;
    pQueueBuffer->aBufferEnd   = QueueBuffer + mSize;
}

void Queue_Push(struct QueueBuffer *pQueueBuffer,unsigned char mData)
{
    //bit fEaReg;

    //fEaReg = EA;
    //EA = 0;
    *pQueueBuffer->pIn++ = mData;
    if(pQueueBuffer->pIn == pQueueBuffer->aBufferEnd)
    {
        pQueueBuffer->pIn = pQueueBuffer->aBufferStart;
    }
    DISABLE_INTERRUPT();
    pQueueBuffer->mCount++;
    ENABLE_INTERRUPT();
    //EA = fEaReg;
}

unsigned char Queue_Pop(struct QueueBuffer *pQueueBuffer)
{
    unsigned char mData;
//    bit fEaReg;

    mData = *pQueueBuffer->pOut;
    if(++pQueueBuffer->pOut == pQueueBuffer->aBufferEnd)
    {
        pQueueBuffer->pOut = pQueueBuffer->aBufferStart;
    }

//    fEaReg = EA;
//    EA = 0;
    DISABLE_INTERRUPT();
    pQueueBuffer->mCount--;
    ENABLE_INTERRUPT();
//    EA = fEaReg;

    return mData;
}

unsigned char Queue_Read(struct QueueBuffer *pQueueBuffer,unsigned char mId)
{
    unsigned char *pTemp;
   
    pTemp = pQueueBuffer->pOut+mId;
    if(pTemp < pQueueBuffer -> aBufferEnd)
    {
        return *pTemp;
    }
    else
    {
        return (*(pTemp-pQueueBuffer->aBufferEnd+pQueueBuffer->aBufferStart));
    }
}

unsigned int Queue_Num (struct QueueBuffer *pQueueBuffer)
{
    unsigned int cnt;
//    bit fEaReg;

//    fEaReg = EA;
//    EA = 0;
    DISABLE_INTERRUPT();
    cnt = pQueueBuffer->mCount;
    ENABLE_INTERRUPT();
//    EA = fEaReg;

    return cnt;
}

void Queue_Clear(struct QueueBuffer *pQueueBuffer)
{
    //bit fEaReg;

    //fEaReg = EA;
    //EA = 0;
    DISABLE_INTERRUPT();
    pQueueBuffer->pIn = pQueueBuffer->pOut = pQueueBuffer->aBufferStart;
    pQueueBuffer->mCount = 0;
    ENABLE_INTERRUPT();
    //EA = fEaReg;
}



    #define TX0_BUFFER_SIZE    32
    #define RX0_BUFFER_SIZE    32
#define DISABLE_RX()    (UCSR0B_Bit4 = 0)
#define ENABLE_RX()     (UCSR0B_Bit4 = 1)
    //modbus constant   
    #define SLAVE_ID                   0x01
    #define MIN_RX_LENGTH              0x08
    #define MAX_RX_LENGTH              0x10     
    #define READ_COIL_STATUS           0x01
    #define READ_INPUT_STATUS          0x02   
    #define READ_HOLDING_REGISTERS     0x03
    #define READ_INPUT_REGISTERS       0x04
    #define WRITE_SINGLE_COIL          0x05
    #define WRITE_SINGLE_REGISTER      0x06
    #define WRITE_MULTIPLE_COILS       0x15
    #define WRITE_MULTIPLE_REGISTERS   0x16
   
    #define TMR2_START()               (TCCR2=0x05)
    #define TMR2_STOP()                (TIFR_Bit6 = 1,TCCR2=0x00)  
    #define TMR2_RST()                 (TIFR_Bit6 = 1,TCNT2=0x00)
    #define IS_TIMEOUT()               (TIFR_Bit6)

    extern void Usart0_Init(void);
    extern void Usart0_FrameCtrl(void);


        
        #define UART0_RX_PUSH(x)    Queue_Push(&sQueueRx0Buf,x)
        #define UART0_RX_POP()      Queue_Pop(&sQueueRx0Buf)
        #define UART0_RX_READ(x)    Queue_Read(&sQueueRx0Buf,x)
        #define UART0_RX_NUM()      Queue_Num(&sQueueRx0Buf)
        #define UART0_RX_CLR()      Queue_Clear(&sQueueRx0Buf)
   
        #define UART0_TX_PUSH(x)    Queue_Push(&sQueueTx0Buf,x)
        #define UART0_TX_POP()      Queue_Pop(&sQueueTx0Buf)
        #define UART0_TX_READ(x)    Queue_Read(&sQueueTx0Buf,x)
        #define UART0_TX_NUM()      Queue_Num(&sQueueTx0Buf)
        #define UART0_TX_CLR()      Queue_Clear(&sQueueTx0Buf)
   
        struct QueueBuffer sQueueTx0Buf;
        struct QueueBuffer sQueueRx0Buf;
   
        unsigned char g_QueueTx0Buf[TX0_BUFFER_SIZE];
        unsigned char g_QueueRx0Buf[RX0_BUFFER_SIZE];

//
void Usart0_Init(void)
{
    // USART0 initialization
    // Communication Parameters: 8 Data, 1 Stop, No Parity
    // USART0 Receiver: On
    // USART0 Transmitter: On
    // USART0 Mode: Asynchronous
    // USART0 Baud Rate: 4800
    UCSR0A=0x00;
    UCSR0B=0xD8;
    UCSR0C=0x06;
    UBRR0H=0x00;
    UBRR0L=0xCF;

    Queue_Register(&sQueueTx0Buf,g_QueueTx0Buf,TX0_BUFFER_SIZE);
    Queue_Register(&sQueueRx0Buf,g_QueueRx0Buf,RX0_BUFFER_SIZE);
    TMR2_RST();
    TMR2_STOP();
}



void FrameHeaderCheck(void)
{
    if(UART0_RX_NUM() == 1)
    {
        if(UART0_RX_READ(0) == SLAVE_ID)
        {
            TMR2_RST();
            TMR2_START();
        }
        else
        {
            UART0_RX_POP();
        }
    }
}

bool IsFrameTrailer(void)
{
    if(IS_TIMEOUT())
    {
        TMR2_STOP();
        return 1;
    }
    else
    {
        return 0;
    }
}

void Usart0_FrameCtrl(void)
{
    unsigned char rx_length;
    unsigned int regAddr;
    unsigned int regNum;
    unsigned char i;
    unsigned int crc16;

    //if(!IsFrameHeader()) return;
    if(!IsFrameTrailer())return;
    DISABLE_RX();
    rx_length = UART0_RX_NUM();
    if((rx_length < MIN_RX_LENGTH)||(rx_length > MAX_RX_LENGTH))
    {
        ENABLE_RX();
        UART0_RX_CLR();
        return;
    }
    if(CRC16_Calculator(g_QueueRx0Buf,rx_length) != 0)
    {   
        ENABLE_RX();
        UART0_RX_CLR();
        return;
    }
    regAddr = (UART0_RX_READ(2)<<8)|UART0_RX_READ(3);
    regNum  = (UART0_RX_READ(4)<<8)|UART0_RX_READ(5);

    switch(UART0_RX_READ(1))
    {
        case READ_HOLDING_REGISTERS:
            UART0_RX_CLR();
            UART0_TX_CLR();
            if((regAddr + regNum) > 6)//register address 0-5 and number = 6
            {
                break;
            }
            UART0_TX_PUSH(SLAVE_ID);
            UART0_TX_PUSH(READ_HOLDING_REGISTERS);
            UART0_TX_PUSH(regNum*2);
            for(i=0; i<regNum; i++)
            {
                UART0_TX_PUSH(LiBATT.bVoltTab[regAddr+i]>>8);
                UART0_TX_PUSH(LiBATT.bVoltTab[regAddr+i]);
                //Queue_Push(&sQueueTx0Buf,LiBATT.bVoltTab[regAddr+i]>>8);
                //Queue_Push(&sQueueTx0Buf,LiBATT.bVoltTab[regAddr+i]);
            }
            crc16 = CRC16_Calculator(g_QueueTx0Buf,regNum*2+3);
            UART0_TX_PUSH(crc16);
            UART0_TX_PUSH(crc16>>8);
            UDR0 = UART0_TX_POP();
            //Queue_Push(&sQueueTx0Buf,crc16>>8);
            //Queue_Push(&sQueueTx0Buf,crc);
            //UDR0 = Queue_Pop(&sQueueTx0Buf);
            break;
        default:
            break;
    }
}

/*!
* __interrupt void USART0_RXC_ISR (void)
* describe:
*
*
*
*
* \author
*
* \
*/
#pragma vector = USART0_RXC_vect
__interrupt void USART0_RXC_ISR(void)
{
    unsigned char udr;
    udr = UDR0;
    UART0_RX_PUSH(udr);
    FrameHeaderCheck();
    TMR2_RST();
}

/*!
* __interrupt void USART0_TXC_ISR (void)
* describe:
*
*
*
*
* \author
*
* \
*/
#pragma vector = USART0_TXC_vect
__interrupt void USART0_TXC_ISR(void)
{
    if(UART0_TX_NUM() != 0)
    {
        UDR0 = UART0_TX_POP();   
    }
    else
    {
        ENABLE_RX();
    }
}

这里只是展示一下Queue.c的具体应用~~这个程序经调试的~~~

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2009-3-11 16:49:01 | 显示全部楼层
没有人感兴趣啊~~

出0入0汤圆

发表于 2009-3-11 17:07:02 | 显示全部楼层
一句注释都没有,可读性太差了,即便程序再好。

出0入0汤圆

 楼主| 发表于 2009-3-11 17:19:01 | 显示全部楼层
呵呵,这个程序很容易实现各种各样的串行通讯协议~~~

出0入0汤圆

发表于 2009-3-11 18:58:51 | 显示全部楼层
好的代码,是不需要太多的注释……

出0入0汤圆

发表于 2009-3-11 19:59:21 | 显示全部楼层
顶一个!

出0入0汤圆

发表于 2009-3-12 07:46:45 | 显示全部楼层
怎么用,楼主给个使用范例才好

出0入0汤圆

 楼主| 发表于 2009-3-12 08:12:02 | 显示全部楼层
这里就是一个应用啊~~

出0入0汤圆

发表于 2009-3-13 16:20:23 | 显示全部楼层
怎么样与自己的程序结合起来理解呢?

出0入0汤圆

发表于 2009-3-13 16:34:16 | 显示全部楼层
可读性太差!

出0入0汤圆

发表于 2009-3-13 16:40:59 | 显示全部楼层
我那个注释还可以 谁帮我补补

出0入0汤圆

发表于 2009-3-13 16:52:49 | 显示全部楼层
写的不错,不过还真厉害,一个注释没有啊.

出0入0汤圆

 楼主| 发表于 2009-3-13 17:22:06 | 显示全部楼层
呵呵,老农的代码有注释的,被我DELETE了~~~

出0入0汤圆

发表于 2010-9-6 13:55:26 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-6 14:59:26 | 显示全部楼层
Mark

出0入0汤圆

发表于 2010-10-7 15:35:38 | 显示全部楼层
回复【4楼】zlei
好的代码,是不需要太多的注释……
-----------------------------------------------------------------------

谬论~

出0入0汤圆

发表于 2010-12-24 10:19:33 | 显示全部楼层
你这叫发的啥啊

出0入0汤圆

发表于 2011-5-22 10:45:51 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-22 11:04:49 | 显示全部楼层
老农是谁?

出0入0汤圆

发表于 2011-5-23 12:14:10 | 显示全部楼层
modbusrtu 很好,触摸屏通讯可以考虑

出0入0汤圆

发表于 2011-5-23 13:19:44 | 显示全部楼层
好代码,无需注释
本人一目十行看过来 都能明白个大概

出0入0汤圆

发表于 2012-4-5 16:40:00 | 显示全部楼层
俺是新手,没有注释,再好的源码,俺看了也晕!

出0入0汤圆

发表于 2012-4-5 16:46:19 | 显示全部楼层
mark~~~~~~

出0入85汤圆

发表于 2012-4-5 16:52:36 | 显示全部楼层
估计没人看

出0入0汤圆

发表于 2012-8-22 13:57:35 | 显示全部楼层
mark~~~~~~~

出0入0汤圆

发表于 2012-9-20 23:39:29 | 显示全部楼层

出0入0汤圆

发表于 2012-11-26 23:25:34 | 显示全部楼层
看看,读代码就头痛

出0入0汤圆

发表于 2012-11-27 13:01:14 | 显示全部楼层
如果能给我们程序框图就容易明白了

出0入76汤圆

发表于 2012-11-27 21:14:22 | 显示全部楼层
是用IAR写的.....
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 04:10

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表