PIC 单片机软件异步串行口实现技巧
/发送队列 unsigned char outPtr, //发送队列指针 outTotal, //发送的字节总数 chkSum; //发送的校验码 //===================================================================== // 主程序 //===================================================================== void main(void) { PORTA = 0; PORTB = 0; TRISB = 0b01; //输入输出定义 OPTION = 0b10000000; //TMR0选择内部指令周期计数 //TMR0预分频 1:2 rsRx.state = RS_IDLE; //初始化接收状态 rsTxBusy = 0; //发送空闲 INTCON = 0b00100000; //T0IE使能 GIE = 1; //打开中断 while(1) { //程序主循环 asm("clrwdt"); //清看门狗 UART_In(); //接收串行数据 UART_Out(); //发送串行数据 } } //===================================================================== // 查询在接收FIFO队列中是否有新数据到 //然后解读数据 //===================================================================== void UART_In(void) { unsigned char data1; if (rsRx.putPtr==rsRx.getPtr) return; //如果读取和存放的指针相同,则队列为空 data1 = rsRx.dataBuff[rsRx.getPtr]; //读取1个数据字节 rsRx.getPtr++; //调整读取指针到下一位置 rsRx.getPtr &= 0x07; //考虑环形队列回绕 //此处为数据解读分析,略 } //===================================================================== // 软件UART发送数据 //数据在outBuff中,outTotal为总字节数 //===================================================================== void UART_Out(void) { if (rsTxBusy==1) return; //正处于移位发送忙 //可以发送新数据 if (outTotal) { //如果有字节要发送 rsTx.shiftBuff = outBuff[outPtr++]; //取字节到发送移位寄存器 rsTxBusy = 1; //置发送忙标志,启动发送 outTotal--; //字节计数器减1 } } //=================================================================== // 中断服务程序 //=================================================================== void interrupt isr(void) { //利用TMR0 定时中断实现全双工软件UART if (T0IE && T0IF) { T0IF = 0; //清TMR0中断标志 //实现串行接收 RX 状态机控制 switch (rsRx.state) { //判当前接收状态 case RS_IDLE: //当前状态为"空闲", 唯一要做的就是判"起始位"出现 if (RX_PIN==0) { //如果接收到低电平 rsRx.sliceCount = 4; //准备4*Ts时间间隔 rsRx.shiftCount = 8; //总共接收8位数据位 //改变此数值可以实现任意位数的数据接收 rsRx.state = RS_DATA_BIT; //切换到数据位接收状态 } break; case RS_DATA_BIT: //当前状态为"数据接收" if (--rsRx.sliceCount==0) { //等采样时间到 rsRx.shiftBuff >>= 1; //接收移位寄存器右移1位 if (RX_PIN) rsRx.shiftBuff|=0x80; //保存最新收到的数据位 rsRx.sliceCount = 3; //下次采样间隔为3*Ts if (--rsRx.shiftCount==0) { //已经收到8位数据位? //保存数据字节到FIFO缓冲队列 rsRx.dataBuff[rsRx.putPtr] = rsRx.shiftBuff; //队列存放指针调整,最多8个字节缓冲 rsRx.putPtr = (rsRx.putPtr+1) & 0x07; //转去下个状态,判停止位 rsRx.state = RS_STOP_BIT; } } break; case RS_STOP_BIT: //当前状态为停止位判别(此程序没有判别) if (--rsRx.sliceCount==0) { //等采样时间到 //此处可以判RX_PIN是否为1 rsRx.state = RS_IDLE; //复位接收过程 } break; default: //异常处理 rsRx.state = RS_IDLE; //复位接收过程 } //实现串行发送 TX 状态机控制 switch (rsTx.state) { //判当前发送状态 case RS_IDLE: //发送起始位 if (rsTxBusy) { //如果发送启动 TX_PIN = 0; //发出起始位低电平 rsTx.sliceCount = 3; //持续时间3*Ts rsTx.shiftCount = 8; //数据位数为8位 rsTx.state = RS_DATA_BIT; //转去下一状态 } else TX_PIN = 1; //如果没有数据发送则保证数据线为空闲 break; case RS_DATA_BIT: //发送8位数据位 if (--rsTx.sliceCount==0) { //码元宽度定时到 if (rsTx.shiftBuff & 0x01)//看数据位是0还是1 TX_PIN = 1; //发送1 else TX_PIN = 0; //发送0 rsTx.shiftBuff >>= 1; //准备下次数据位发送 rsTx.sliceCount = 3; //数据位宽度为3*Ts if (--rsTx.shiftCount==0) { //8位数据位发送结束,转去发送停止位 rsTx.stat
- dsPIC33F系列DSC的 SD存储卡接口设计(01-05)
- 基于dsPIC30F2010的土壤水分测量仪的设计研究(08-27)
- 基于AD7862和dsPIC30F的数据采集系统(08-25)
- 基于DSPIC30F4011单片机的CAN总线通信设计(02-08)
- PICCl8编译器命令行驱动及其应用(02-11)
- 基于dsPIC33F系列单片机的应用程序升级方法(04-03)