⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 io-uart.c

📁 C51的IO模拟UART,非常好用,对于缺少串口的51单片机很好!
💻 C
字号:
/********************************************************************************/
/* filename: uart.c                                                             */
/* version : v1.00                                                              */
/* created : hw-chen                                                            */
/********************************************************************************/
#include "extern.h"

#define VM_XMIT_LEN         0x40
#define VM_XMIT_MSK         0x3F
#define VM_RXD              P3_2    //* 需要利用外部中断0
#define VM_TXD              P3_3

unsigned char data recv_vm_steps=0x0;
unsigned char data recv_vm_flags=0x0;
unsigned char data recv_vm_mdata=0x0;
unsigned char data recv_vm_sbuff=0x0;
unsigned char data xmit_vm_steps=0x0;
unsigned char data xmit_vm_flags=0x0;
unsigned char data xmit_vm_mdata=0x0;
unsigned char xmit_vm_buffer[VM_XMIT_LEN];
unsigned char xmit_vm_wr=0x0;
unsigned char xmit_vm_rd=0x0;
unsigned char recv_vm_buffer[VM_RECV_LEN];
unsigned char recv_vm_wr=0x0;

/********************************************************************************/
/* function : vm_io_initialize()                                                */
/* created  : hw-chen                                                           */
/* descript : 初始化虚拟串口                                                    */
/********************************************************************************/
void vm_io_initialize(void)
{   EX0=0x1;
    IT0=0x1;   //* 设置INT0为下降沿中断方式
    xmit_vm_steps=0x0;
    xmit_vm_flags=0x0;
    xmit_vm_mdata=0x0;
    xmit_vm_wr   =0x0;
    xmit_vm_rd   =0x0;
    recv_vm_wr   =0x0;
    recv_vm_steps=0x0;
    recv_vm_flags=0x0;
    recv_vm_mdata=0x0;
}

/********************************************************************************/
/* fun_name : timer_0_initialize()                                              */
/* descript : called by main initialize                                         */
/* version  : v1.00                                                             */
/* created  : hw-chen                                                           */
/*   1200的波特率,每位数据需要833.3US,每位数据的中间采样,起始位的中间只有一半   */
/*   的时间,定时器为416.667US,然后其他位都是833.3US                             */
/*   起始位:VALUE=65536-50000000x0.0004167/12=0xF938-0x10                       */
/*   其它位:VALUE=65536-50000000x0.0008333/12=0xF270-0x10                       */
/*   由于不是自动加载,需要减去系统的压栈和中断响应周期,查看汇编需要16指令周期   */
/********************************************************************************/
void timer_0_initialize(void)
{   TMOD &= 0xF0;   //* TMOD: timer 0, mode 1, 16-bit load
    TMOD |= 0x01;   //* 模式1,16位模式
    TR0   = 0x0;
}

/********************************************************************************/
/* function : timer_2_initialize()                                              */
/* created  : hw-chen                                                           */
/* descript :                                                                   */
/*    由于采用VM串口的发送定时器,1200的波特率,每位定时0.8333MS=0.0008333S       */
/*    VALUE=65536-(oscxtime(s))/12=65536-50000000 x0.0008333/12(=3472 )         */
/*    定时器2处于16位自动加载模式,不会产生定时误差                              */
/********************************************************************************/
void timer_2_initialize(void)
{   RCAP2H= 0xF2;
    RCAP2L= 0x70;
    TR2   = 0x01;
    ET2   = 0x01;
}

/********************************************************************************/
/* function : extern_0_interrupt()                                              */
/* created  : hw-chen                                                           */
/* descript :                                                                   */
/********************************************************************************/
void extern_0_interrupt(void) interrupt 0 using 1
{   vm_start_bit_check_start();
}

/********************************************************************************/
/* function : timer_0_interrupt()                                               */
/* created  : hw-chen                                                           */
/* descript : 用作VM串口接收处理                                                */
/********************************************************************************/
void timer_0_interrupt(void) interrupt 1 using 1
{   recv_mdata_isr_process();
}

/********************************************************************************/
/* function : timer_2_interrupt()                                               */
/* created  : hw-chen                                                           */
/* descript : 用作VM串口发送处理                                                */
/*      0.8333MS定时器                                                          */
/********************************************************************************/
void timer_2_interrupt(void) interrupt 5 using 1
{   TF2=0;                      //* 需要自己清楚中断标记
    xmit_mdata_isr_process();   //* 处理VM的ISR发送细节
}

/********************************************************************************/
/* function : main()                                                            */
/* created  : hw-chen                                                           */
/* descript :                                                                   */
/********************************************************************************/
void main(void)
{   timer_0_initialize();
    vm_io_initialize();
    timer_2_initialize();
    EA =0x1;
    ET2=0x1;
    IT0=0x1;
    ET0=0x1;
    EX0=0x1;   //* 打开外部VM-RXD管脚的中断
    uart_printf("*********************************\r\n");
    uart_printf("* VM UART start ...             *\r\n");
    uart_printf("*********************************\r\n");
    while(1){
    xmit_SBUF_mdata_process();  //* 发送SBUF的数据
    recv_SBUF_mdata_process();  //* 接收SBUF的数据
    }
}

/********************************************************************************/
/* function : xmit_SBUF_mdata_process()                                         */
/* created  : hw-chen                                                           */
/* descript : 发送数据处理,在主函数里面调用                                     */
/********************************************************************************/
void xmit_SBUF_mdata_process(void)
{   if((xmit_vm_flags)) //* 正在发送数据
    {   return;
    }
    if((xmit_vm_rd==xmit_vm_wr))
    {   return;
    }
    xmit_vm_mdata=xmit_vm_buffer[xmit_vm_rd];
    xmit_vm_rd++;
    xmit_vm_rd&=VM_XMIT_MSK;
    VM_TXD=0x1;                 //* 起始位
    xmit_vm_steps=0x0;          //* 设置起始步
    xmit_vm_flags=0x1;          //* 启动发送,正在发送数据标记
}

/********************************************************************************/
/* function : xmit_mdata_isr_process()                                          */
/* created  : hw-chen                                                           */
/* descript : VM发送数据中断处理函数                                            */
/********************************************************************************/
void xmit_mdata_isr_process(void)
{   if((xmit_vm_flags)==0x0)
    {   return;
    }
    xmit_vm_steps++;
    switch(xmit_vm_steps)
    {
    case 0x1:
         VM_TXD=0x0;
         break;
    case 0x2:
         if((xmit_vm_mdata&0x1)==0x1)
         VM_TXD=0x1;
         else
         VM_TXD=0x0;
         break;
    case 0x3:
         if((xmit_vm_mdata&0x2)==0x2)
         VM_TXD=0x1;
         else
         VM_TXD=0x0;
         break;
    case 0x4:
         if((xmit_vm_mdata&0x4)==0x4)
         VM_TXD=0x1;
         else
         VM_TXD=0x0;
         break;
    case 0x5:
         if((xmit_vm_mdata&0x8)==0x8)
         VM_TXD=0x1;
         else
         VM_TXD=0x0;
         break;
    case 0x6:
         if((xmit_vm_mdata&0x10)==0x10)
         VM_TXD=0x1;
         else
         VM_TXD=0x0;
         break;
    case 0x7:
         if((xmit_vm_mdata&0x20)==0x20)
         VM_TXD=0x1;
         else
         VM_TXD=0x0;
         break;
    case 0x8:
         if((xmit_vm_mdata&0x40)==0x40)
         VM_TXD=0x1;
         else
         VM_TXD=0x0;
         break;
    case 0x9:
         if((xmit_vm_mdata&0x80)==0x80)
         VM_TXD=0x1;
         else
         VM_TXD=0x0;
         break;
    case 0xA:
         VM_TXD=0x1;
         break;
    default:
         VM_TXD=0x1;
         xmit_vm_flags=0x0;  //* 数据发送完毕
         xmit_vm_steps=0x0;  //* 复位起始步
         break;
    }
}

/********************************************************************************/
/* function : vm_start_bit_check_start()                                        */
/* created  : hw-chen                                                           */
/* descript : 设置VM开始位检测                                                  */
/********************************************************************************/
void vm_start_bit_check_start(void)
{   EX0=0x0;            //* 需要关闭外部VM-RXD管脚的中断
    recv_vm_steps=0x0;
    recv_vm_flags=0x0;
    recv_vm_mdata=0x0;
    TR0=0x00;
    TH0=0xF9;           //* 只需要一半的时间
    TL0=0x48;
    TR0=0x01;
}

/********************************************************************************/
/* function : recv_mdata_isr_process()                                          */
/* created  : hw-chen                                                           */
/* descript : 开始接收数据                                                      */
/********************************************************************************/
void recv_mdata_isr_process(void)
{   TR0=0x00;
    TH0=0xF2;
    TL0=0x80;
    TR0=0x01;
    recv_vm_steps++;
    switch(recv_vm_steps)
    {
    case 0x1:
         if((VM_RXD)){
         IE0=0x0;   //* 必须清除这个标记
         TR0=0x0;   //* 禁止定时器
         EX0=0x1;   //* 打开外部VM-RXD管脚的中断
         }
         break;
    case 0x2:
         if((VM_RXD))
         recv_vm_mdata|=0x1;
         else
         recv_vm_mdata&=0xFE;
         break;
    case 0x3:
         if((VM_RXD))
         recv_vm_mdata|=0x2;
         else
         recv_vm_mdata&=0xFD;
         break;
    case 0x4:
         if((VM_RXD))
         recv_vm_mdata|=0x4;
         else
         recv_vm_mdata&=0xFB;
         break;
    case 0x5:
         if((VM_RXD))
         recv_vm_mdata|=0x8;
         else
         recv_vm_mdata&=0xF7;
         break;
    case 0x6:
         if((VM_RXD))
         recv_vm_mdata|=0x10;
         else
         recv_vm_mdata&=0xEF;
         break;
    case 0x7:
         if((VM_RXD))
         recv_vm_mdata|=0x20;
         else
         recv_vm_mdata&=0xDF;
         break;
    case 0x8:
         if((VM_RXD))
         recv_vm_mdata|=0x40;
         else
         recv_vm_mdata&=0xBF;
         break;
    case 0x9:
         if((VM_RXD))
         recv_vm_mdata|=0x80;
         else
         recv_vm_mdata&=0x7F;
         break;
    case 0xA:
         if((VM_RXD)){
         recv_vm_flags=0x1;
         }
         recv_vm_sbuff=recv_vm_mdata;
         IE0=0x0;   //* 必须清除这个标记
         TR0=0x0;   //* 停止定时器
         EX0=0x1;   //* 打开外部VM-RXD管脚的中断
         break;
    default:
         IE0=0x0;   //* 必须清除这个标记
         TR0=0x0;   //* 停止定时器
         EX0=0x1;   //* 打开外部VM-RXD管脚的中断
         break;
    }
}

/********************************************************************************/
/* function : vm_printf()                                                       */
/* created  : hw-chen                                                           */
/* descript : 从VM串口输出信息                                                  */
/********************************************************************************/
void vm_printf(char *string, ...)
{   unsigned char i,length;
    char buffer[0x40];
    va_list arguments;

    va_start(arguments,string);
    vsprintf(buffer,string,arguments);
    va_end(arguments);

    length=strlen(buffer);
    for(i=0x0;i<length;i++){
    if((xmit_vm_wr+0x1)==xmit_vm_rd)
    {   break;
    }
    xmit_vm_buffer[xmit_vm_wr]=buffer[i];
    xmit_vm_wr++;
    xmit_vm_wr&=VM_XMIT_MSK;
    }
    return;
}

/********************************************************************************/
/* function : recv_SBUF_mdata_process()                                         */
/* created  : hw-chen                                                           */
/* descript : VM串口接收数据处理                                                */
/********************************************************************************/
void recv_SBUF_mdata_process(void)
{   if(recv_vm_flags==0x0)
    {   return;
    }
    recv_vm_flags=0x0;
    if((recv_vm_sbuff==0x8)&&(recv_vm_wr>0x0)){ /* 处理退格 */
    recv_vm_wr--;
    vm_printf("%c",0x8);
    vm_printf("%c",' ');
    vm_printf("%c",0x8);
    return;
    }
    recv_vm_buffer[recv_vm_wr]=recv_vm_sbuff; /* 接收处理 */
    recv_vm_wr++;
    if((recv_vm_sbuff=='\r')||(recv_vm_sbuff=='\n'))
    {   recv_command_process();
    }
    if((recv_vm_wr>=VM_RECV_MSK))
    {   recv_vm_wr=0x0;
    }
    else
    {   vm_printf("%c",recv_vm_sbuff);  /* 回显 */
    }
}

/********************************************************************************/
/* function : recv_command_process()                                            */
/* created  : hw-chen                                                           */
/* descript : VM串口接收数据处理                                                */
/********************************************************************************/
void recv_command_process(void)
{   recv_vm_buffer[recv_vm_wr]=0x0;
    //* 添加自己的处理函数
    recv_vm_wr=0x0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -