编程点滴:AVR的I/O端口模拟UART串口测试程序

发布者:ching80790最新更新时间:2016-10-21 来源: eefocus关键字:AVR  I  O端口  模拟UART  串口测试 手机看文章 扫描二维码
随时随地手机看文章
本程序用软件模拟AVR的I/O端口,实现UART端口收发功能。

定时器中断轮流处理接收/发送端口的数据接收/发送工作,自然数据传输波特率为定时器中断频率的1/2。如有必要,定时器中断也可轮流处理更多端口的收发工作,以支持模拟更多串口,相应每个端口的数据处理速度也会进一步降低。

以下为程序文件:测试程序,数据处理程序及头文件



/* ****************************************************************
* File name: main.c
* Function: AVR的I/O端口模拟串口测试程序
* Description: 1. 通过定时器中断轮流处理端口收发, 模拟UART数据收发功能
* 2. 外部晶振频率16.0MHz, 预分频值8, 定时器timer频率9600Hz,
* 定时器比较值207, 模拟串口波特率4800bps, 全双工异步模式,
* 支持模拟1个串口, 提高定时器频率或降低波特率, 1个定时器
可以支持模拟更多串口
* Author & Date: Joshua Chan, 2012/03/30
* ****************************************************************/
#include
#include
#include
#include
#include
#include "sim_uart_test.h"

/* 测试程序: 将接收的数据送出 */
void main(void)
{
unsigned char data;

var_init(); /* 初始化变量 */
port_init(); /* 配置收发端口 */
timer0_init(); /* 配置定时器 */
_SEI(); /* 全局中断使能 */
while (1) {
if ((data = rx_byte()) != NONE_DATA)
tx_byte(data);
_WDR();
}
}




/* ****************************************************************
* File name: sim_uart_test.h
* Function: AVR的I/O端口模拟串口测试程序
* Description: 1. 通过定时器中断轮流处理端口收发, 模拟UART数据收发功能
* 2. 外部晶振频率16.0MHz, 预分频值8, 定时器timer频率9600Hz,
* 定时器比较值207, 模拟串口波特率4800bps, 全双工异步模式,
* 支持模拟1个串口, 提高定时器频率或降低波特率, 1个定时器
可以支持模拟更多串口
* Author & Date: Joshua Chan, 2012/03/30
* ****************************************************************/
#ifndef _SIM_UART_TEST_H
#define _SIM_UART_TEST_H

/* PE0: 模拟UART接收端口
* PE1: 模拟UART发送端口
* PE0/PE1为硬件自带UART0的RX/TX口, 测试时需将其UART功能关闭
*/
#define GET_RX() (PINE & (1< #define SET_TX() (PORTE |= (1< #define CLR_TX() (PORTE &= ~(1<
#define NONE_DATA '\4' /* 无新数据标志 */

/* 定义接收队列 */
#define RX_FIFO_SIZE 4 /* 接收队列大小 */
#define TX_FIFO_SIZE 4 /* 发送队列大小 */

/* 定时器中断发生时的读写周期 */
enum timer_turn {
RX_TURN = 0, /* 读周期 */
TX_TURN, /* 写周期 */
};

/* 数据帧结构 */
__flash enum frame_bit {
BIT_0 = 0,
BIT_1,
BIT_2,
BIT_3,
BIT_4,
BIT_5,
BIT_6,
BIT_7,
BIT_STOP,
BIT_IDLE,
BIT_START,
};

/* 变量初始化 */
extern void var_init(void);

/* 配置收发端口 */
extern void port_init(void);

/* 配置定时器 */
extern void timer0_init(void);

/* 从接收队列读1字节 */
extern unsigned char rx_byte(void);

/* 向发送队列写1字节 */
extern void tx_byte(unsigned char data);

#endif




/* ****************************************************************
* File name: sim_uart_test.c
* Function: AVR的I/O端口模拟串口测试程序
* Description: 1. 通过定时器中断轮流处理端口收发, 模拟UART数据收发功能
* 2. 外部晶振频率16.0MHz, 预分频值8, 定时器timer频率9600Hz,
* 定时器比较值207, 模拟串口波特率4800bps, 全双工异步模式,
* 支持模拟1个串口, 提高定时器频率或降低波特率, 1个定时器
可以支持模拟更多串口
* Author & Date: Joshua Chan, 2012/03/30
* ****************************************************************/
#include
#include
#include
#include
#include
#include "sim_uart_test.h"

unsigned char rx_fifo[RX_FIFO_SIZE]; /* 定义接收队列 */
unsigned char tx_fifo[TX_FIFO_SIZE]; /* 定义发送队列 */

unsigned char rx_pos; /* 队列中最后接收数据位置 */
unsigned char read_pos; /* 队列中最后读取数据位置 */
unsigned char tx_pos; /* 队列中最后发送数据位置 */
unsigned char write_pos; /* 队列中最后写入数据位置 */

unsigned char rx_buf; /* 接收字节缓冲 */
unsigned char tx_buf; /* 发送字节缓冲 */
volatile unsigned char rx_bit; /* 接收帧位计数 */
volatile unsigned char tx_bit; /* 发送帧位计数 */

volatile unsigned char current_turn; /* 轮流读写周期标志 */

/* 变量初始化 */
void var_init(void)
{
rx_pos = 0;
read_pos = 0;
tx_pos = 0;
write_pos = 0;

/* 定义初始收发位为空闲位 */
rx_bit = BIT_IDLE;
tx_bit = BIT_IDLE;

current_turn = RX_TURN;
}

/* 配置定时器 */
void timer0_init(void)
{
TCCR0 = ((1< TIMSK = (1< OCR0 = 207; /* 比较值207, 定时器频率: 16.0MHz/((207+1)*8) = 9600Hz */
TCNT0 = 0;
}

/* 配置收发端口 */
void port_init(void)
{
UCSR0B = 0; /* 关闭PE0/PE1上的硬件UART */
DDRE &= ~(1 << DDE0); /* PE0输入 */
DDRE |= (1 << DDE1); /* PE1输出 */
}

/* 从接收队列读1字节 */
unsigned char rx_byte(void)
{
if (read_pos != rx_pos) {
if (++read_pos == RX_FIFO_SIZE)
read_pos = 0;
return rx_fifo[read_pos];
} else {
return NONE_DATA;
}
}

/* 向发送队列写1字节 */
void tx_byte(unsigned char data)
{
if (++write_pos == TX_FIFO_SIZE)
write_pos = 0;
tx_fifo[write_pos] = data;
}

/* 定时器读周期处理函数 */
static void rx_turn_isr(void)
{
switch (rx_bit) { /* 根据当前帧位执行相应操作 */
case BIT_IDLE:
if (!GET_RX()) /* 检测起始位, 以判断是否有数据待收 */
rx_bit = BIT_0;
break;
case BIT_0: /* 开始接收数据 */
case BIT_1:
case BIT_2:
case BIT_3:
case BIT_4:
case BIT_5:
case BIT_6:
case BIT_7:
if (GET_RX()) /* 根据端口电平, 写接收缓冲相应位 */
rx_buf |= (1 << rx_bit);
else
rx_buf &= ~(1 << rx_bit);
rx_bit++;
break;
case BIT_STOP:
if (GET_RX()) { /* 检测停止位, 出现帧错误则丢弃数据, 否则写入接收队列 */
if (++rx_pos == RX_FIFO_SIZE)
rx_pos = 0;
rx_fifo[rx_pos] = rx_buf;
}
rx_bit = BIT_IDLE;
break;
}
}

/* 定时器写周期处理函数 */
static void tx_turn_isr(void)
{
switch (tx_bit) { /* 根据当前帧位执行相应操作 */
case BIT_START:
CLR_TX(); /* 输出起始位 */
tx_bit = BIT_0;
break;
case BIT_0: /* 开始发送数据 */
case BIT_1:
case BIT_2:
case BIT_3:
case BIT_4:
case BIT_5:
case BIT_6:
case BIT_7:
if (tx_buf & (1 << tx_bit)) /* 根据待发数据位信息, 控制发送端电平 */
SET_TX();
else
CLR_TX();
tx_bit++;
break;
case BIT_STOP:
case BIT_IDLE:
SET_TX();
if (tx_pos != write_pos) { /* 检测是否有待发数据, 无则发送空闲位 */
if (++tx_pos == TX_FIFO_SIZE)
tx_pos = 0;
tx_buf = tx_fifo[tx_pos];
tx_bit = BIT_START;
} else {
tx_bit = BIT_IDLE;
}
break;
}
}

/* 定时器中断处理函数 */
#pragma vector = TIMER0_COMP_vect
__interrupt void timer0_isr(void)
{
switch (current_turn) {
case RX_TURN: /* 读周期 */
rx_turn_isr();
current_turn = TX_TURN;
break;
case TX_TURN: /* 写周期 */
tx_turn_isr();
current_turn = RX_TURN;
break;
}
}

 
关键字:AVR  I  O端口  模拟UART  串口测试 引用地址:编程点滴:AVR的I/O端口模拟UART串口测试程序

上一篇:C51单片机和AVR单片机的区别
下一篇:编程点滴:AVR timer0 配置模块

推荐阅读最新更新时间:2024-03-16 15:16

AVR单片机的特性介绍
RISC(精简指令系统计算机)是相对于CISC(复杂指令系统计算机)而言的。RISC 并非只是简单地去减少指令,而是通过使计算机的结构更加简单合理而提高运算速度的。RISC 优先选取使用频率最高的简单指令,避免复杂指令:并固定指令宽度,减少指令格式和寻址方式的种类,从而缩短指令周期,提高运行速度。由于 AVR 采用了 RESC 的这种结构,使AVR系列单片机都具备了1MIPS/MHz(百万条指令每秒/兆赫兹)的高速处理能力。 AVR单片机吸收了 DSP 双总线的特点,采用 Harvard 总线结构,因此单片机的程序存储器和数据存储器是分离的,并且可对具有相同地址的程序存储器和数据存储器进行独立的寻址。 在 AVR单片机中,
[单片机]
AVR单片机的T/C2与精确时钟C程序
CodeWizardAVR V1.25.6 Professional Chip type : ATmega48 Clock frequency : 7.372800 MHz Memory model : Small External SRAM size : 0 Data Stack size : 128 计算: 1秒 = 时钟 / ( 分频 * 计数 ) 假设时钟 = 7372800 Hz 那么: 1秒 = 7372800 / ( 分频 * 计数 ) 得: 计数 =7372800/分频 由于分频只有 1/8/32/64/128/256/1024 供我们选择,而计数最高只有8
[单片机]
AVR单片机C语言的使用特点
PORTX和PINX的使用区别 AVR单片机每组I/O口有3个8位寄存器,分别是DDRx、PORTx和PINx; DDR用于控制I/O口的输入输出方向: DDRx=1时,I/O口输出,PORTx=1时输出高电平,PORTx=0时输出低电平, DDRx=0时,I/O口输入,这时要读取外部管脚的电平就应读取PINx中的数值,而不是PORTx; PORTx是数据寄存器,而PINx不能称为真正意义上的寄存器,更像是一个可控的三态口 引用 几种单片机C语言的中断程序写法 本文引用自Ajiao《几种单片机C语言的中断程序写法》 引用 Ajiao的 几种单片机C语言的中断程序写法 Keil C51编译器: void int
[单片机]
AVR单片机I/O口、定时器和按键编程总结
首先,用到了定时器2的溢出中断,用于控制灯的闪烁。在这部分程序的设计中,遇到的困难是当灯一旦闪烁起来,就无法控制其它的内容了。后来明白是由于中断服务程序太长,没等执行完计数器就计满了,然后就一直的在执行闪烁程序,导致无法在执行其它命令。最开始在每次延迟函数之后令计数器置零,可是还是没有起到太大效果,因为最长的延迟函数为2s,时间太长,最后经考虑,在进入中断服务程序的时候,屏蔽定时器2溢出中断,在离开之前再使能,然后再令计数器置零,结果实现了所要的结果。 第二个问题就是关于按键。要求相应的I/O口即能做输出,又能做输入,能够用按键控制。似乎很简单的一个程序,可是第一次做也遇到不少问题。当按下相应的按键,就给data赋一个值,去实现不同
[单片机]
利用具有I/O模拟多路复用器的PSoC简化传感器控制设计
赛普拉斯公司的CY8C21×34可编程系统级芯片(PSoC)混合信号阵列具有一个I/O模拟多路复用器,由于每个引脚都可以被用作一个模拟输入,因此采用单个SoC便能够轻松实现需要大量不同类型传感器的控制应用。本文介绍了在多种传感器控制应用中如何利用该器件来简化设计。 图1:模拟多路复用器/系统连接。 工业控制应用常常需要许多模拟输入,即使是具有一个PWM输出的最简单的风扇控制器也有可能需要对数量众多的温度传感器进行监控。模拟输入是宝贵的资源,经常很快就会被消耗殆尽。在很多场合,设计工程师不得不采用一个更加昂贵的部件,从而导致一些多余的空闲资源,或者必须增加外部多路复用器,以满足对模拟输入信号访问次数增加的需要。而
[模拟电子]
avr单片机定时与中断做的电子琴(仿真+程序)
仿真原理图如下 avr单片机源码: #include iom16v.h #include macros.h #define uchar unsigned char #define uint unsigned int #define LED1_ON() PORTA=0xFE #define LED2_ON() PORTA=0xF7 #define LED3_ON() PORTA=0xBF #define LED4_ON() PORTA=0x7F uchar key_0=16; uint Fr = {0,262*8,294*8,330*8,349*8,392*8,440*8, 494*8,523*8,
[单片机]
<font color='red'>avr</font>单片机定时与中断做的电子琴(仿真+程序)
Microchip推出全新功能安全型AVR® DA系列单片机,支持实时控制、连接和HMI应用
随着物联网(IoT)为工业和家庭应用提供更强的连接性,以及车联网提升了驾驶室和操控功能,业界需要更高性能的单片机来实现更好的实时控制以及增强的人机接口应用。Microchip Technology Inc.(美国微芯科技公司)日前宣布推出下一代AVR® DA系列单片机(MCU),是其首款带有外设触摸控制器(PTC)的功能安全型AVR MCU系列。 Microchip 8位单片机事业部助理营销副总裁Greg Robinson表示:“新推出的AVR DA单片机系列继承了Microchip高性能和高代码效率器件的优势,通过搭载先进模拟和独立于内核的外设,以及比现有器件更多的电容式触摸通道,满足了多个行业的新需求。新的单片机系列产品广
[汽车电子]
Microchip推出全新功能安全型<font color='red'>AVR</font>® DA系列单片机,支持实时控制、连接和HMI应用
基于AVR微控制器的交流信号峰值检测与校正
摘要:微控制器外围电路的设计已经是一个比较成熟的领域,相比硬件,软件系统的研发周期更短,投入更少,在中国更加具有发展空间。基于AVR单片机的硬件结构和工作原理,采用一种全新的检测交流信号峰值的算法,并辅以相应的自校正算法来实现精确的峰值检测。通过硬件上的实现证明此种算法的速度非常快,精度高达0.1%,在测控工业应用中具有非常好的前景。 关键词:峰值检测;自我校正;算法 0 引言 单片机在民用电子产品中的应用主要以测量和控制为主。一个完整的单片机系统除了健全的软件系统外,往往还需要外围电路的支持。而现如今,对一些传统电路的设计已经非常成熟,因此在硬件上要想有所突破要比在软件算法的突破难得多。拿峰值检波电路来说,理论上,交流
[工业控制]
基于<font color='red'>AVR</font>微控制器的交流信号峰值检测与校正
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved