在CVAVR系统提供的标准库函数stdio.h中,提供了getchar()函数,该函数是采用轮询方式从USART接收数据的,轮询方式不仅效率低,而且会丢失数据,不能实现多任务的并行处理。
CVAVR程序向导中给出的采用中断+缓冲的方式接受数据,同PC的串口接受数据的方法一样,充分利用了AVR的高速和RAM多的优点,体现出了如何才能充分发挥AVR的特点的程序设计思想,这种思路在32位系统中也是这样的。
使用AVR的话,对软件的设计能力要求更高了,否则根本不能发挥和体现AVR的特点。许多人有了一点C的基础,就认为采用C编写单片机程序没问题,很快就会掌握AVR了,对此我只能一笑了之。看看本站上众多的代码,再看看本贴的遭遇,能说什么呢?
回到本题:
注1:
如果在程序的开头部分加上语句
#define _DEBUG_TERMINAL_IO_
那么程序在编译时仍使用系统自己的getchar()函数,这样在软件模拟仿真时,可以从模拟的终端读取数据,便于在软件模拟环境中调试整个系统,而需要正式运行时,则把该句注释掉。
注2:
此处在正式应用中应根据实际情况做适当的修改。否则当主程序调用getchar()时,如果缓冲队列中没有数据,同时对方也没有发数据的情况时,程序会在此死循环。
比较简单的办法是将这句删掉,而在调用getchar()函数前先判断rx_counter的值,为0的话就不调用了。
或改为:
signed int getchar(void)
{
signed int data;
if (rx_counter == 0)
{
data = -1;
}
else
{
data=rx_buffer[rx_rd_index]; //读取缓冲队列中的数据
if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0; //读取指针指向下一个未读的数据,如果指到了队列尾部,则指回到队列头步
#asm("cli") // 关中断!非常重要
--rx_counter; //队列中未读数据个数减1。因为该变量在接收中断中要改变的,为了防止冲突,所以改动前临时关闭中断。程序相当可靠了。
#asm("sei") // 开中断
}
return data;
}
注3:
有兴趣希望深入实在学习的网友,可将CVAVR生成的USART发送代码仔细分析以下。它的发送代码非常完美,可以马上使用。
#include
#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7
#define FRAMING_ERROR (1<
#define PARITY_ERROR (1<
#define DATA_OVERRUN (1<
#define DATA_REGISTER_EMPTY (1<
#define RX_COMPLETE (1<
// USART Transmitter buffer
#define TX_BUFFER_SIZE