通博TBET

新闻中心
AVR单片机模拟串口 定时器方案 模拟USART RS232
2010-11-27
7534

程序文件

[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]

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

上一篇: GSM短信模块通过AT指令发送短信到小灵通的方法 下一篇: AVR单片机利用按键控制发光二极管的亮灭 IO实验 返回首页
热门推荐
热门标签