程序文件
[code="c"]
/*********************************************************************************************************
** AVR软件 串口驱动
** (c) Copyright 2010, limaokui
** All Rights Reserved
**
** V1.0.0
**
**
**--------------文件信息--------------------------------------------------------------------------------
**文 件 名:iousart.c
**创 建 人: www.avrvi.com
**最后修改日期: 2010年5月7日
**描 述: AVR软件 串口驱动,占用定时器1,无引脚中断
**注 意: 软件耗时比较多,注意开中断.
*********************************************************************************************************/
#include "config.h"
unsigned char Baud=0;
volatile unsigned char SimComBuf;
volatile unsigned char SimComTxSampleCycle=0;
volatile unsigned char bSimComTxing;//正在发送标志
unsigned char bSimComWaitCheck;//受到一条命令,等待处理
unsigned char bSimComRxLoadBit;//已接受到开始位
volatile unsigned char bSimComRxDropEdge;//侦测开始位的第一周期已开始
volatile unsigned char SimComRxBitCount;//接受一个字节10位计数器
volatile unsigned char SimComRxSampleCycle;//位采样周期计数器
volatile unsigned char SimComRxBit,SimComRxSampleBuf;
unsigned char SimComSBuf;//接受寄存器暂存
unsigned char bSimComByteWaitCheck;//受到一byte,等待处理
volatile unsigned char SimComSendBitCount;//已发送位数计数器
volatile unsigned char SimComSendBuf;//发送缓冲区
unsigned char *ptSimComTxBuf;//发送缓冲区指针
unsigned char SimComSendByteCount;//已发送字节数计数器
unsigned char SimComOutputA=0xff;
void iousart_init(unsigned char baudrate)
{
DDRTXD|=(1<<BITTXD);
PORTTXD|=(1<<BITTXD);
DDRRXD&=~(1<<BITRXD);
PORTRXD|=(1<<BITRXD);
TCCR0 = 0x00; //stop
Baud=baudrate;
switch (baudrate)
{
case 0: TCNT0 = 0xE0; //set count 0xC0 1200bps @14.7456Mhz
break;
case 1: TCNT0 = 0xF0; //set count 0xE0 2400bps @14.7456Mhz
break;
case 2: TCNT0 = 0xF8; //set count 0xF0 4800bps @14.7456Mhz
break;
case 3: TCNT0 = 0xFC; //set count 0xF8 9600bps @14.7456Mhz
break;
default:TCNT0 = 0xE0; //set count 1200bps @14.7456Mhz
}
TCCR0 = 0x03; //start timer
TIMSK |= (1<<TOIE0);
}
#pragma interrupt_handler timer0_ovf_isr:iv_TIMER0_OVF
void timer0_ovf_isr(void)
{
unsigned char i,j,bitStatu;
//unsigned char SimComOutputTemp;
switch (Baud)
{
case 0: TCNT0 = 0xE0; //set count 1200bps @14.7456Mhz
break;
case 1: TCNT0 = 0xF0; //set count 2400bps @14.7456Mhz
break;
case 2: TCNT0 = 0xF8; //set count 4800bps @14.7456Mhz
break;
case 3: TCNT0 = 0xFC; //set count 9600bps @14.7456Mhz
break;
default:TCNT0 = 0xE0; //set count 1200bps @14.7456Mhz
}
if((SimComOutputA & (1<<BITTXD)))
{
PORTTXD |= (SimComOutputA & (1<<BITTXD));//发送
}
else
{
PORTTXD &= SimComOutputA ; //发送
}
SimComBuf = PINRXD;//接收
++SimComTxSampleCycle;
if(SimComTxSampleCycle>=3)
{
SimComTxSampleCycle=0;
}
//------接受-------------------------
bitStatu=(1<<BITRXD);
//------SimCom RX-------
if(((bSimComTxing & bitStatu) == 0)
&& ((bSimComWaitCheck & bitStatu) == 0))
{
if((bSimComRxLoadBit & bitStatu) == 0)
{//检测开始位
if((bSimComRxDropEdge & bitStatu) == 0)//未检测到下降缘,继续检测
{
if((SimComBuf & bitStatu) == 0)//采样为底电平
{
SimComRxBitCount=0;
bSimComRxDropEdge |= bitStatu;
SimComRxSampleCycle=1;
SimComRxBit=0xff;
}
}
else//已检测到下降缘,检查是否为引导位
{
SimComRxSampleCycle++;
if(SimComRxSampleCycle==2)
{
if((SimComBuf & bitStatu)==0)//采样为底电平
{
SimComRxBit=0;
}
else
{
SimComRxBit=0x80;
}
}
else if(SimComRxSampleCycle>=3)//已采样3个周期--1位采样结束
{
if(SimComRxBit==0)
{
bSimComRxLoadBit |= bitStatu;//==‘0’
}
bSimComRxDropEdge &= ~bitStatu;
SimComRxSampleCycle=0;
SimComRxBitCount=0;
}
}
}
else
{//数据位和停止位
//-----采样1位-----
SimComRxSampleCycle++;
if(SimComRxSampleCycle==1)
SimComRxBit=0xff;
if(SimComRxSampleCycle==2)
{
if((SimComBuf & bitStatu)==0)//采样为底电平
SimComRxBit = 0;
else
SimComRxBit = 0x80;
}
else if(SimComRxSampleCycle >= 3)//每位采样3个周期
{
SimComRxSampleCycle = 0;
//-----
++SimComRxBitCount;
if(SimComRxBitCount<=8)
{
SimComRxSampleBuf >>= 1;
SimComRxSampleBuf |= SimComRxBit;
}
else
{
bSimComRxLoadBit &= ~bitStatu;
bSimComRxDropEdge &= ~bitStatu;
if(SimComRxBit==0x80)
{//正确的停止位
SimComSBuf=SimComRxSampleBuf;
bSimComByteWaitCheck |= bitStatu;
}
}
}
}
}
//------发送下一位 ------------------
if(SimComTxSampleCycle == 0)
{
SimComOutputA = 0xff;
if(bSimComTxing > 0)
{
SimComSendBitCount++;
if(SimComSendBitCount == 1)//引导位
{
SimComOutputA &= ~bSimComTxing;
SimComSendBuf = *ptSimComTxBuf;
}
else if(SimComSendBitCount < 10)//8个数据位
{
i=SimComSendBuf;
SimComSendBuf >>= 1;
if((i & 0x01) == 0)
SimComOutputA &= ~bSimComTxing;
}
else if(SimComSendBitCount == 10)//停止位
{
ptSimComTxBuf++;
SimComSendBitCount = 0;
if(SimComSendByteCount > 0)
{
SimComSendByteCount--;
}
if(SimComSendByteCount == 0)
{
bSimComTxing = 0;
}
}
/* else if(SimComSendBitCount >= 11)//休止位
{
SimComSendBitCount = 0;
if(SimComSendByteCount > 0)
{
SimComSendByteCount--;
}
if(SimComSendByteCount == 0)
{
bSimComTxing = 0;
}
} */
}
}
//SimComOutputA &=0x0f;
SEI();
}
unsigned char Get_Char(void)
{
while((bSimComByteWaitCheck&(1<<BITRXD))==0);
bSimComByteWaitCheck=0x00;
return SimComSBuf;
}
unsigned char Soft_Receive_one(void)
{
bSimComByteWaitCheck=0x00;
return SimComSBuf;
}
void Put_String(unsigned char *ptr,unsigned char num)
{
bSimComTxing=(1<<BITTXD);
SimComSendByteCount=num;
ptSimComTxBuf=ptr;
}
/* 以下为测试
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x01; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void main(void)
{
unsigned char TXBUF[10];
init_devices();
iousart_init(3);
while(1)
{
TXBUF[0]=Get_Char();
Put_String(TXBUF,1);
}
}
*/
[/code]
头文件:
[code="c"]
#ifndef __iosesOFTUSART__
#define __iosesOFTUSART__
#define DDRTXD DDRB
#define PORTTXD PORTB
#define BITTXD 6
#define DDRRXD DDRB
#define PORTRXD PORTB
#define PINRXD PINB
#define BITRXD 7
//定义 14.7456Mhz 下波特率常量
#define Baud_1200 0
#define Baud_2400 1
#define Baud_4800 2
#define Baud_9600 3
extern void iousart_init(unsigned char baudrate);
//带死等的接收
extern unsigned char Get_Char(void);
//直接返回,先判断后调用,它取完数之后会改变标志位
extern unsigned char Soft_Receive_one(void);
//标志位
extern unsigned char bSimComByteWaitCheck;
#define Soft_Receive_flag (bSimComByteWaitCheck&(1<<BITRXD))
extern void Put_String(unsigned char *ptr,unsigned char num);
#endif
[/code]
还有中断方式的方案,请点击下面的模拟串口标签以查找下载链接。