📄 uart.c
字号:
//*****************************************************************************
//
// File........: UART.c
//
// Author(s)...: ATMEL Norway
//
// Target(s)...: ATmega169
//
// Compiler....: IAR EWAAVR 2.27b
//
// Description.: UART transmittion
//
// Revisions...: 1.0
//
// YYYYMMDD - VER. - COMMENT - SIGN.
//
// 20021015 - 1.0 - Created - LHM
//
//*****************************************************************************
// Include files
#include "Main.h"
#include "UART.h"
// Global variables
unsigned char RX_byte_nr; // counts the number of received bytes
unsigned char sPreamble[] = "STK502"; // the preamble to detect start of frame
unsigned char ReceiveBuffer[50]; // recevive buffer to temporary store the received data
unsigned char TransmitBuffer[50]; // transmit buffer to temporary store the data to be transmitted
unsigned char TX_byte_nr; // counts the number of transmitted bytes
unsigned char Bytes_to_send; // cointains the number of bytes to send
unsigned char RX_Packet_complete = FALSE; // if received a whole packet it's TRUE, else it will be FALSE
unsigned char RX_Preamble_complete = FALSE; // if preamble has been received it's TRUE, else it will be FALSE
unsigned char Dec_L; // Decimal low byte
unsigned char Dec_M; // Decimal medium byte
unsigned char Dec_H; // Decimal high byte
/******************************************************************************
*
* Function name: UART_init
*
* returns: none
*
* parameters: baudrate, used to set the baudrate of the UART
*
* Purpose: Initialise the UART
*
*******************************************************************************/
void UART_init(unsigned char BaudRate)
{
RX_byte_nr = 0;
UBRR0L = BaudRate; // set the baudrate that is choosen
UCSR0A = (1<<U2X0); // double the USART Transmission Speed
UCSR0B = (1<<RXCIE0) | (1<<TXCIE0) | (1<<RXEN0) | (1<<TXEN0); // enable Receiver and Transmitter and interrupt
UCSR0C = (3<<UCSZ00); // character size = 8 bit
}
/******************************************************************************
*
* Function name: Store_RX_data
*
* returns: none
*
* parameters: none
*
* Purpose: Convert from ASCII to HEX and store data from the ReceiveBuffer
* to the SRAM locations
*
*******************************************************************************/
void Store_RX_data(void)
{
unsigned char ASCII_Cnt = 0; // variable to count the number of ascii-bytes
unsigned char HEX_Cnt = 0; // variable to count the number of Hex-bytes
unsigned char HEX_byte; // variable to store the Hex-byte
// loop until the Packet is converted from ascii to Hex and loaded in the correct places in SRAM
while(RX_Packet_complete)
{
HEX_byte = 0; // clear "HEX_byte"
// loop to convert ASCII to Hex
// it will loop until a ascii space charater (0x20) or a ascii line feed (0x0D) appears
while((ReceiveBuffer[ASCII_Cnt] != 0x20) & (ReceiveBuffer[ASCII_Cnt] != 0x0D))
{
HEX_byte *= 10; // multiply Hex-byte with 10
HEX_byte += (ReceiveBuffer[ASCII_Cnt] - '0'); // store and add the ascii-byte
ASCII_Cnt++; // increment ascii byte counter
} // one ascii-byte has been converted to a Hex-byte
if(ASCII_Cnt) // if any byte where converted
{
*(&HOUR + HEX_Cnt) = HEX_byte; // store the Hex-byte in SRAM
HEX_Cnt++; // increment Hex-byte counter
}
if(ReceiveBuffer[ASCII_Cnt] == 0x20) // if the ascii byte was a space charater
ASCII_Cnt++; // increment ascii byte counter
else // else it means the end of packet
{
RX_Packet_complete = FALSE; // indicate that a new packet can be converted
}
} //the whole ReceiveBuffer has been converted Hex-bytes and stored in the SRAM-locations
}
/******************************************************************************
*
* Function name: Send_TX_data
*
* returns: none
*
* parameters: none
*
* Purpose: Send data from the TransmitBuffer
*
*******************************************************************************/
void Send_TX_data(void)
{
unsigned char Nr_bytes_in_TX_buffer;
unsigned char Cnt;
unsigned char Nr_ASCII_bytes;
if(!(UCSR0B & 0x20)) // do not make a new transmit-buffer if there's an on-going transmition (UDRIE-bit is set)
{
//FILL THE TRANSMITBUFFER WITH NEW DATA
Nr_bytes_in_TX_buffer = 0; // clear number of bytes in buffer
// load preamble byte in the transmit-buffer
while(sPreamble[Nr_bytes_in_TX_buffer])
{
TransmitBuffer[Nr_bytes_in_TX_buffer++] = sPreamble[Nr_bytes_in_TX_buffer]; //put the preamble to the Transmit buffer
}// finished loading the preamble byte
Cnt = 0; // clear "Cnt", which is used to count the number of bytes loaded from SRAM in the loop below
// load data bytes in the transmit-buffer
while(Cnt < Nr_of_hex_bytes_to_send) // loop until "Cnt" is equal to "Nr_of_hex_bytes_to_send
{
TransmitBuffer[Nr_bytes_in_TX_buffer++] = 0x20; // add one space character
Nr_ASCII_bytes = HEX2ASCII(*(&HOUR + Cnt++)); // format Hex-byte to ACSII data-bytes
while(Nr_ASCII_bytes) // loop while there's ASCII to left
{
Nr_ASCII_bytes--; // decrement "Nr_ASCII_bytes"
TransmitBuffer[Nr_bytes_in_TX_buffer++] = *(&Dec_L + Nr_ASCII_bytes); // load ASCII-bytes in the transmit-buffer
}
}// finished loading data bytes in the transmit-buffer
TransmitBuffer[Nr_bytes_in_TX_buffer++] = 0x20; // add one space character
TransmitBuffer[Nr_bytes_in_TX_buffer++] = REVISION_H; // add the revisions number in the transmit packet
TransmitBuffer[Nr_bytes_in_TX_buffer++] = REVISION_L; // add the revisions number in the transmit packet
TransmitBuffer[Nr_bytes_in_TX_buffer++] = 0x0D; // load ASCII for carriage return
TransmitBuffer[Nr_bytes_in_TX_buffer++] = 0x0A; // load ASCII for line feed
TX_byte_nr = 0; // no bytes sent
Bytes_to_send = Nr_bytes_in_TX_buffer; // set number of bytes to send = nr_bytes_in-TX_buffer
UCSR0B |= (1<<UDRIE0); // Enable UDRE interrupt (starts transfer)
}
}
/******************************************************************************
*
* Function name: HEX2ASCII
*
* returns: Number of decimal-bytes
*
* parameters: The Hex-byte to be converted
*
* Purpose: Converts a Hex-byte to 2 or 3 decimal-bytes
*
*******************************************************************************/
unsigned char HEX2ASCII(unsigned char Hex)
{
unsigned char Nr_ASCII_bytes = 2;
Dec_L = 0; //clear decimal-bytes
Dec_M = 0;
Dec_H = 0;
while(Hex) // loop until the Hex is zero
{
Dec_L = Hex; // store decimal-byte to Dec_L
Hex -= 10; // subtract 10 from the Hex-byte
if(!(SREG & 0x01)) // if carry flag is not set
{
Dec_M++; // incrase Dec_M-byte
if(Dec_M > 9) // if Dec_M-byte over 100 decimal
{
Dec_M = 0; // clear Dec_M
Dec_H++; // increase Dec_H
}
if(!Hex) // if the Hex is zero
Dec_L = 0; // clear Dec_L
}
else
Hex = 0;
}
Dec_L += 0x30; // add 0x30 to get the rigth ascii-value
Dec_M += 0x30; // add 0x30 to get the rigth ascii-value
if(Dec_H) // if over 100d
{
Dec_H += 0x30; // add 0x30 to get the rigth ascii-value
Nr_ASCII_bytes++; // increase number of bytes
}
return Nr_ASCII_bytes; // return number of bytes
}
/******************************************************************************
*
* USART0 Receive Interrupt Routine
*
*******************************************************************************/
#pragma vector = USART0_RXC_vect
__interrupt void USART0_RXC_interrupt(void)
{
unsigned char RX_byte;
RX_byte = UDR0; // read the UDR0 register
if((RX_byte == sPreamble[RX_byte_nr]) & !RX_Preamble_complete) // if received byte matches predicted preamble byte
{ // and Preamble string hasn't been received
RX_byte_nr++;
if(RX_byte_nr == (sizeof(sPreamble) - 1)) // if all preamble bytes has been received
{
RX_Preamble_complete = TRUE; // indicate that the preable byte is OK
RX_byte_nr = 0;
}
}
else if(RX_Preamble_complete) // if the Preamble string has been received
{
ReceiveBuffer[RX_byte_nr++] = RX_byte; // store the received byte to the receivebuffer
if(RX_byte == 0x0D) // if Packet_length is zero, send back a buffer immediately
{
ReceiveBuffer[RX_byte_nr++] = RX_byte; // store the received byte in to the reveivebuffer
RX_Preamble_complete = FALSE; // set the RX_Preamble_complete to FALSE, so the function will start to search for a new preamble
RX_Packet_complete = TRUE; // set RX_Packet_complete so the converting of the received packet can start
RX_byte_nr = 0;
}
}
else
RX_byte_nr = 0;
}
/******************************************************************************
*
* USART0 Data Register Empty Interrupt Routine
*
*******************************************************************************/
#pragma vector = USART0_UDRE_vect
__interrupt void USART0_UDRE_interrupt(void)
{
if (TX_byte_nr < Bytes_to_send)
{
UDR0 = (TransmitBuffer[TX_byte_nr++]); //Put byte from Transmit buffer to USART I/O Data Register
}
else
{
UCSR0B &= ~(1<<UDRIE0); // Disable UDRE interrupt, transmission finshied
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -