最新动态

工业物联网通讯专家!
认真做好每一件事,设计简单、可靠、价格合理的产品!

AVR单片机模拟串口 定时器方案 模拟USART RS232

程序文件

/********************************************************************************************************* **                                      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); } } */

头文件:

#ifndef __IOSOFTUSART__ #define __IOSOFTUSART__ #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

还有中断方式的方案,请点击下面的模拟串口标签以查找下载链接。



上一篇: Windows操作系统25年发展历程
下一篇: 单片机自关机(彻底关机)电路的实现方法

发表评论