用软件模拟单片机串口程序(1)

来源:互联网 发布:&&在c语言中是什么意思 编辑:程序博客网 时间:2024/05/22 15:05
 利用PCA解决软件串口的问题。PCA包含一个专用的16位计数器/定时器和五个16位的捕捉比较模块,每个模块都可以在被设置为在PCA计数器与相对应的比较模块的内容一致时产生中断。由于PCA计数器在产生中断时并不停止运行,所以可避免中断延迟累加的问题。本例还编写了用硬件串口HW_UART来测试模拟串口SW_UART。由HW_UART发送15个字符,SW_UART接收。同时由SW_UART发送15个字符,HW_UART接收。
     #include<c8051f000.h>
 #define BAUD_RATE  57600                                     //用户定义的波特率
 
 #define SYSCLK 18432000                                     //系统时钟取自外部18.432MHZ晶体
 
 #define TIME_COUNT SYSCLK/BAUD_RATE/4                      //对应一个位时间的PCA计数值
 
 #define TH_TIME_COUNT TIME_COUNT*3/2                      //3/2位时间,在接受到一个起始位之后
                                                          //使用。在起始位边沿之后RX应在一个位
               //时间内保持低电平,第一个位采样在下一
                                                        //个位时间的中间开始
 
 
 #define HW_TIME_COUNT SYSCLK/BAUD_RATE/16              //用于产生HW_UART波特率的定时计数值。
 //-------------------------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------------------------
 bit SRI;                           //接收完成标志
 bit STI;                           //发送完成标志
 bit STXBSY;                        //发送忙标志
 bit SREN;                          //接收允许
 
 sbit SW_RX=P0^2;                   //接收引脚
 sbit SW_TX=P0^3;                   //发送引脚
 
 char TDR;                          //发送数据寄存器
 char RDR;                          //接收数据寄存器
 
 
 //测试变量
 char k,m;                          //测试计数器
 char idata SW_BUF[20];             //测试接收缓冲区
 
 bit HW_DONE;                       //HW发送结束标志(发送完15个字符)
 bit SW_DONE;                       //SW发送结束标志
 //-----------------------------------------------------------------------------------------------
    //函数原型
 //-----------------------------------------------------------------------------------------------
 void SW_UART_INIT();                //SW_UART初始化程序
 void SW_UART_ENEABLE();             //SW_UART允许程序
 void PCA_ISR();                     //SW_UART中断服务程序
 void POLLED_TEST(void);             //SW_UART查询方式测试程序
 void HWU_INIT(void);                //HW_UART初始化程序
 void HW_UART_ISR(void);             //HW_UART中断服务程序
 //----------------------------------------------------------------------------------------------
 //------------------------------------------------------------------------------------------------
 void MAIN(void)
 {
  int delay;
  OSCXCN=0x66;                    //允许外部晶体
  WDTCN=0xDE;                     //禁止看门狗定时器 
  WDTCN=0xAD;
 
  XBR0=0x0C;
  XBR2=0x40;
  PRT0CF=0x09;
 
 
  delay=256;                       //在查询XTLVLD之前延时>1ms
  while(!(OSCXCN & 0x80));         //等待外部晶体起振
     OSCXCN=0x0C;                     //切换到外部振荡器
  OSCXCN=0x88;
 
 while(!(OSCXCN & 0x80));          //等待外部晶体起振
  OSCXCN=0x08;                     //切换到外部振荡器
 
 
  POLLED_TEST();                  //调用查询方式SW_UART测试程序
  while(1);
 
 
 }
 
 //----------------------------------------------------------------------------------------------
    //函数
 //----------------------------------------------------------------------------------------------
 
 void POLLED_TEST(void)
 {
   SW_UART_INIT();                //初始化SW_UART
   SW_UART_ENEABLE();             //允许SW_UART
   SREN=1;                        //允许SW_UART接收器
  
   HWU_INIT();                    //配置HW_UART,用于测试程序
   k=m=0;                         //请0测试计数器变量
   HW_DONE=0;                     //请0传送完成标志
   SW_DONE=0;
   IE|=0x10;                      //允许HW_UART中断
   TI=1;                           //HW_UART发送
 //-----------------------------------------------------------------------------------------------
    //用SW_UART接收15个字符;用HW_UART发送
   while(SREN)                    //在SW_UART被允许时执行
   {
     if(SRI){                    //如果接收完成
        SRI=0;                   //清楚接收标志
        SW_BUF[k++]=RDR;         //读接收缓冲区 
        if(k==15){               //如果已收到15个字符
           SREN=0;               //禁止SW_UART接收器
                  }
            }
 }
  //=================================================================================================
  //用SW_UART发送15个字符;用HW_UART接收
    while(STXBSY);              //查询忙标志
    STXBSY=1;                   //占用SW_UART发送器
    TDR=m++;                    //装发送数据
    CCF1=1;                     //通过强制PCA模块1中断来启动第一次SW_UART发送


    while(!SW_DONE)           
 {
   
         if(STI){              //如果发送完成
            STI=0;             //清除发送标志
            if(m<16){          //发送15个字符
               STXBSY=1;       //占用SW_UART发送器
               TDR=m++;       //发送,变量增1
               CCF1=1;        //强制模块1中断以启动发送
                    }
        else
               SW_DONE=1;
                }
 }
}
 
 //-------------------------------------------------------------------------------------
 void HWU_INIT(void)
 {
  PCON|=0x80;                //SMOD=1(HW_UART使用定时器1溢出,不分频)
  TMOD=0x20;                 //配置定时器1为HW_UART所用
  CKCON|=0x10;              //定时器1用SYSCLK作为时钟
  TH1=-HW_TIME_COUNT;        //定时器1初始值
  TL1=-HW_TIME_COUNT;        //定时器1重装载
  TR1=1;                    //启动定时器1
  RI=0;                     //清除HW_UART接受和发送 
  TI=0;
  SCON=0x50;               //配置HW_UART为方式1,允许接受
 }
 
 //-------- --------------------------------------------------------------------------
 void SW_UART_INIT(void)
 {
  PCA0CPM0=0x10;            //模块0为负沿捕捉方式,禁止模块0中断
  PCA0CPM1=0x48;            //模块1为软件定时器方式,禁止模块1中断
  PCA0CN=0;                 //PCA保持禁止状态              
  PCA0MD=0x02;              //PCA时基=SYSCLK/4;禁止PCA计数器中断
  CCF0=0;                   //清除PCA模块0和1捕捉比较模块
  CCF1=0; 
                
  SRI=0;                   //清楚接受完成标志
  STI=0;                    //清除发送完成标志
  SW_TX=1;                  //将TX线初始化为高电平
  STXBSY=0;                 //清除SW_UART忙标志
 }
 //----------------------------------------------------------------------------------
 void SW_UART_ENEABLE(void){
 
  PCA0CPM0|=0x01;           //允许PCA模块0(接收中断)
  PCA0CPM1|=0x01;           //允许PCA模块1(发送中断)
  CR=1;                    //启动PCA计数器
  EIE1|=0x08;              //允许PCA中断
  EA=1;                     //全局中断允许
 }
0 0