很久就在用这个功能,一直很好用。现在整理了一下,把这个软件帖出来,希望对大家有用处。 可以用于232或485通讯。通过预编译选择。
以下uart.h:
#ifndef _uart_h #define _uart_h
#include "avr/io.h"
#define TURE 1 #define FALSE 0
#define RS485MODE TURE //TURE:rs485 FALSE:rs232
#define BAUDRATE 51 //baud rate #define UART_buffer_size 32 //must 1,2,4,8,16,32,64,128 or 256 bytes
#if (RS485MODE == TURE) #define TX_EN PIND2 #define TX_DDR DDRD #define TX_PORT PORTD #define RS_485_port_init() TX_DDR |= (1<<TX_EN) #define RS_485_send() TX_PORT |= (1<<TX_EN) //RS485 enable #define RS_485_receive() TX_PORT &= ~(1<<TX_EN) //RS485 disable #endif
//-------------------------------------------------------------------------------------- //UART Buffer Defines //-------------------------------------------------------------------------------------- #define UART_RX_BUFFER_SIZE UART_buffer_size #define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1 ) #define UART_TX_BUFFER_SIZE UART_buffer_size #define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1 )
#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK ) #error RX buffer size is not a power of 2 #endif #if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK ) #error TX buffer size is not a power of 2 #endif
//-------------------------------------------------------------------------------------- //unsigned char ReceiveByte( void ) //Parameters: none //Function: Read a byte from uart //Notice: None //Created: 2005-3-1 , By zsmbj //-------------------------------------------------------------------------------------- unsigned char ReceiveByte( void );
//-------------------------------------------------------------------------------------- //void TransmitByte( unsigned char data ) //Parameters: //Function: write a byte to uart //Notice: None //Created: 2005-3-1 , By zsmbj //-------------------------------------------------------------------------------------- void TransmitByte( unsigned char data );
//-------------------------------------------------------------------------------------- //unsigned char DataInReceiveBuffer( void ) //Parameters: //Function: if have a uart data then return 1 //Notice: None //Created: 2005-3-1 , By zsmbj //-------------------------------------------------------------------------------------- unsigned char DataInReceiveBuffer( void );
#endif
以下uart.c:
#include "uart.h" #include "avr/interrupt.h"
/**********************************************************************/ /* These are the global variables */ /**********************************************************************/ //UART related buffers and variables unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE]; volatile unsigned char UART_RxHead; volatile unsigned char UART_RxTail;
unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE]; volatile unsigned char UART_TxHead; volatile unsigned char UART_TxTail;
/**********************************************************************/ /* UART subroutine. */ /**********************************************************************/
/* initialize UART */ void init_UART( void ) { UBRRL = BAUDRATE; //set the baud rate UBRRH = 0; //enable UART receiver and transmitter, and receive interrupt
UCSRA = 0; UCSRB = ( (1<<RXCIE) | (1<<RXEN) | (1<<TXEN) ); UCSRC = ( (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) ); UART_RxTail = 0; //flush receive buffer UART_RxHead = 0; UART_TxTail = 0; UART_TxHead = 0;
#if (RS485MODE == TURE) RS_485_port_init(); RS_485_receive(); #endif }
//-------------------------------------------------------------------------------------- //SIGNAL (SIG_UART_RECV) //Parameters: none //Function: uart rxd interrupt //Notice: None //Created: 2005-3-1 , By zsmbj //-------------------------------------------------------------------------------------- SIGNAL (SIG_UART_RECV) { unsigned char data; unsigned char tmphead;
data = UDR; //read the received data tmphead = ( UART_RxHead + 1 ) & UART_RX_BUFFER_MASK; //calculate buffer index UART_RxHead = tmphead; //store new index if ( tmphead == UART_RxTail ) //ERROR! Receive buffer overflow {
} UART_RxBuf[tmphead] = data; //store received data in buffer }
//-------------------------------------------------------------------------------------- //SIGNAL (SIG_UART_DATA) //Parameters: none //Function: uart udre interrupt //Notice: None //Created: 2005-3-1 , By zsmbj //-------------------------------------------------------------------------------------- SIGNAL (SIG_UART_DATA) { unsigned char tmptail;
if ( UART_TxHead != UART_TxTail ) //check if all data is transmitted { tmptail = ( UART_TxTail + 1 ) & UART_TX_BUFFER_MASK;//calculate buffer index UART_TxTail = tmptail; //store new index UDR = UART_TxBuf[tmptail]; //start transmition } else { UCSRB &= ~(1<<UDRIE); //disable UDRE interrupt
#if (RS485MODE == TURE) UCSRB |= (1<<TXCIE); //enable TXCIE interrupt #endif } }
//-------------------------------------------------------------------------------------- //SIGNAL (SIG_UART_TRANS) //Parameters: none //Function: uart txd interrupt //Notice: None //Created: 2005-3-1 , By zsmbj //-------------------------------------------------------------------------------------- #if (RS485MODE == TURE) SIGNAL (SIG_UART_TRANS) { RS_485_receive(); //close rs485 send data. UCSRB &= ~(1<<TXCIE); //disable TXCIE interrupt } #endif //-------------------------------------------------------------------------------------- //unsigned char ReceiveByte( void ) //Parameters: none //Function: Read a byte from uart //Notice: None //Created: 2005-3-1 , By zsmbj //-------------------------------------------------------------------------------------- unsigned char ReceiveByte( void ) { unsigned char tmptail;
while ( UART_RxHead == UART_RxTail ) //wait for incomming data ; tmptail = ( UART_RxTail + 1 ) & UART_RX_BUFFER_MASK; //calculate buffer index UART_RxTail = tmptail; //store new index return UART_RxBuf[tmptail]; //return data }
//-------------------------------------------------------------------------------------- //void TransmitByte( unsigned char data ) //Parameters: //Function: write a byte to uart //Notice: None //Created: 2005-3-1 , By zsmbj //-------------------------------------------------------------------------------------- void TransmitByte( unsigned char data ) { unsigned char tmphead;
tmphead = ( UART_TxHead + 1 ) & UART_TX_BUFFER_MASK; //calculate buffer index while ( tmphead == UART_TxTail ) //wait for free space in buffer ; UART_TxBuf[tmphead] = data; //store data in buffer UART_TxHead = tmphead; //store new index
#if (RS485MODE == TURE) RS_485_send(); //open rs485 send data mode if send data ok then close #endif UCSRB |= (1<<UDRIE); //enable UDRE interrupt }
//-------------------------------------------------------------------------------------- //unsigned char DataInReceiveBuffer( void ) //Parameters: //Function: if have a uart data then return 1 //Notice: None //Created: 2005-3-1 , By zsmbj //-------------------------------------------------------------------------------------- unsigned char DataInReceiveBuffer( void ) { return ( UART_RxHead != UART_RxTail ); //return 0 (FALSE) if the receive buffer is empty }
//end of program
以下main.c:测试用
#include "uart.h"
int main(void) { init_UART(); //if received a uart byte then send it if( DataInReceiveBuffer() ) { TransmitByte( ReceiveByte() ); } }
以上程序在winavr20060421下编译通过,单片机atmega8515。
|