|
先上代码:
usart.h
#ifndef __USART_H__
#define __USART_H__
#include <ioavr.h>
#define USART_BAUD_9600 47
#define USART_BAUD_19200 23
#define USART_TX_BUFFER_SIZE 16
#define USART_RX_BUFFER_SIZE 16
void USART_Init( void );
void USART_TransmitByte( unsigned char _data );
void USART_TransmitBuffer( unsigned char *_ptr );
unsigned char USART_ReceiveByte( void );
#endif
usart.c
#include "global_cfg.h"
#include "usart.h"
volatile unsigned char usart_rx_buffer[USART_RX_BUFFER_SIZE];
volatile unsigned char usart_rx_wr_index, usart_rx_rd_index, usart_rx_counter;
volatile unsigned char usart_rx_buffer_overflow;
volatile unsigned char usart_tx_buffer[USART_TX_BUFFER_SIZE];
volatile unsigned char usart_tx_wr_index, usart_tx_rd_index, usart_tx_counter;
void USART_Init(void)
{
UBRRH = 0;
UBRRL = USART_BAUD_9600;
UCSRA = 0x00;
UCSRB_RXEN = 1;
UCSRB_TXEN = 1;
UCSRB_RXCIE = 1;
UCSRB_TXCIE = 1;
//UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE) | (1 << TXCIE);
UCSRC_URSEL = 1;
UCSRC_UCSZ1 = 1;
UCSRC_UCSZ0 = 1;
//UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
usart_rx_wr_index = 0;
usart_rx_rd_index = 0;
usart_rx_counter = 0;
usart_rx_buffer_overflow = 0;
usart_tx_wr_index = 0;
usart_tx_rd_index = 0;
usart_tx_counter = 0;
}
unsigned char USART_ReceiveByte( void )
{
unsigned char data = 0;
//接收数据队列中没有数据可以读取,等待......
while( usart_rx_counter == 0 );
//读取缓冲队列中的数据
data = usart_rx_buffer[usart_rx_rd_index];
//读取指针指向下一个未读的数据,如果指到了队列尾部,则指回到队列头
if( ++usart_rx_rd_index == USART_RX_BUFFER_SIZE )
usart_rx_rd_index = 0;
CLI();
//队列中未读数据个数减1。
//因为该变量在接收中断中要改变的,为了防止冲突,所以改动前临时关闭中断。程序相当可靠了。
--usart_rx_counter;
SEI();
return data;
}
void USART_TransmitByte( unsigned char _data )
{
//发送数据队列中还有数据没有发送完,等待
while( usart_tx_counter == USART_TX_BUFFER_SIZE);
CLI();
//若发送数据队列有数据或者数据寄存器UDR非空时执行
//(因为队列先进先出的原因,所以,c要放进非空的发送数据队列里面)
if( usart_tx_counter || UCSRA_UDRE == 0 )
{
usart_tx_buffer[usart_tx_wr_index] = _data;
if( ++usart_tx_wr_index == USART_TX_BUFFER_SIZE )
usart_tx_wr_index = 0;
++usart_tx_counter;
}
else
UDR = _data;
SEI();
}
void USART_TransmitBuffer( unsigned char *_ptr )
{
while (*_ptr)
{
USART_TransmitByte(*_ptr++);
}
USART_TransmitByte(0x0D);
USART_TransmitByte(0x0A); //结尾发送回车换行
}
#pragma vector = USART_RXC_vect
__interrupt void USART_RXC_interrupt( void )
{
unsigned char status, data;
//读取接收状态标志位,必须先读,当读了UDR后,UCSRA便自动清零了
status = UCSRA;
//读取USART数据寄存器
data = UDR;
//判断本接收到的数据是否有数据帧、校验或数据溢出错误(此处指USART的硬件接收溢出)
if( status & ( ( 1 << FE ) | ( 1 << PE ) | ( 1 << DOR ) ) == 0 )
{
//将数据填充到接收缓冲队列中
usart_rx_buffer[usart_rx_wr_index] = data;
//写指针指向下一个单元,并判断是否到了队列的尾部
if( ++usart_rx_wr_index == USART_RX_BUFFER_SIZE )
//到了尾部,则指向头部
usart_rx_wr_index = 0;
//队列中收到字符加1,并判断是否队列已满
if( ++usart_rx_counter == USART_RX_BUFFER_SIZE )
{
//队列满了,队列中收到字符个数为0,表示队列中所有以前的数据作废,
//因为最后的数据已经把最前边的数据覆盖了
usart_rx_counter = 0;
//置缓冲区溢出标志。在主程序中必要的地方需要判断该标志,以证明读到数据的完整性
usart_rx_buffer_overflow = 1;
}
}
}
#pragma vector = USART_TXC_vect
__interrupt void USART_TXC_interrupt( void )
{
if( usart_tx_counter )
{
--usart_tx_counter;
UDR = usart_tx_buffer[usart_tx_rd_index];
if( ++usart_tx_rd_index == USART_TX_BUFFER_SIZE )
{
usart_tx_rd_index = 0;
}
}
}
这是参考cvavr给出的串口通信例子。我把它修改为IAR EWAVR 5.4下可编译,运行的代码。主程序如下:
#include "global_cfg.h"
#include "delay.h"
#include "usart.h"
unsigned char g_aTXBuffer[29] = {0xAA,0x98,0x00,0xC8,0x00,0xC8,0x00,0x80,0x05,0xF8,0x00,0x00,0x00,0xC9,0xEE,0xDB,0xDA,0xB2,0xCA,0xBE,0xA7,0xBF,0xC6,0xBC,0xBC,0xCC,0x33,0xC3,0x3C};
void main(void)
{
CLI();
USART_Init();
SEI();
DELAY_Seconds(2);
unsigned char i = 0;
for( i = 0; i < 29; i++)
{
USART_TransmitByte(g_aTXBuffer[i]);
}
//USART_TransmitBuffer( "Hello" );
while(1)
{
}
}
这个测试程序在ATMEGA128-16AU的最小系统上可以运行,无错误。但是整个程序放到一个ATMEGA16L的电路板上却运行不了,目标板不工作,用串口通信助手测试,发现收到的全是0.
ATMEGA16L的电路板和目标板可以进行串行通信,我用从教科书上抄来的一段代码测试过,可以正确传输数据。
彻底凌乱了,请高手指点一二。 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。
|