发一个老农的通用单片机程序的AVR移槙-ModbusRTU应用
#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;
unsigned char g_QueueRx0Buf;
//
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>>8);
UART0_TX_PUSH(LiBATT.bVoltTab);
//Queue_Push(&sQueueTx0Buf,LiBATT.bVoltTab>>8);
//Queue_Push(&sQueueTx0Buf,LiBATT.bVoltTab);
}
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的具体应用~~这个程序经调试的~~~ 没有人感兴趣啊~~ 一句注释都没有,可读性太差了,即便程序再好。 呵呵,这个程序很容易实现各种各样的串行通讯协议~~~ 好的代码,是不需要太多的注释…… 顶一个! 怎么用,楼主给个使用范例才好 这里就是一个应用啊~~ 怎么样与自己的程序结合起来理解呢? 可读性太差! 我那个注释还可以 谁帮我补补 写的不错,不过还真厉害,一个注释没有啊. 呵呵,老农的代码有注释的,被我DELETE了~~~ mark Mark 回复【4楼】zlei
好的代码,是不需要太多的注释……
-----------------------------------------------------------------------
谬论~ 你这叫发的啥啊 mark 老农是谁? modbusrtu 很好,触摸屏通讯可以考虑 好代码,无需注释
本人一目十行看过来 都能明白个大概 俺是新手,没有注释,再好的源码,俺看了也晕! mark~~~~~~ 估计没人看{:shy:}{:shy:} mark~~~~~~~ {:smile:}{:smile:}{:smile:}{:smile:} 看看,读代码就头痛 如果能给我们程序框图就容易明白了 是用IAR写的.....
页:
[1]