单片机IO口模拟IrDA1.0协议

IrDA1.0协议是一种利用红外通信的无线传输协议,可以很好的解决一些便携式设备与主机之间通信的问题,具有携带方便,低功耗,成本低,传输可靠等特点,缺点是传输距离较短,速率较慢最高支持(115200波特率)。
此处的irda1.0协议并不是遥控器编解码协议,两者之间编解码方式不一样。国外很多单片机都自带了串口转IrDA1.0的编解码功能,但最近因为换方案,原因找了很多国内单片机都不带IrDA编解码功能,所以在这里为大家提供一个io口模拟IrDA的方案。(原理和串口一样)
单片机使用的是 复旦微的FM33G0XX单片机,红外收发器为 TFBS4652,波特率为9600。
!

图片描述了普通串口调制解调 IrDA之后的波形,IrDA的 TX引脚默认是低电平(普通串口为高电平)所以这里需要将IO口初始化为低电平,IrDA 发送引脚输出3/16宽度的脉冲信号表示低电平。RX引脚默认为高电平,时序与TX一样。
IrDA TX引脚低电平的表示方法:
将一个bit位的时间分为16份,先发送7个周期低电平,然后将io拉高,保持3个周期后将io拉低,保持6个时钟之后继续发送下一个bit。直到一个字节(起始位+数据位+停止位 = 10 bit)数据发送完成.
IrDA TX引脚高电平表示方式:
保持104us (1bit)低电平。
IrDA 3/16 调制
串口发送0时,红外输出3/16宽度的脉冲。串口发送1时,无脉冲。
一个字节包含一个起始位(低电平),8位数据位,1位停止位。(共10位)
有两种方式:1,定时器计时发送,2,软件延时发送。(两种方式均可,需遵守下列时序)本文采用软件延时方式。
IrDA数据发送:
数据发送 采用定时器中断发送数据,9600波特率我们可以知道 一个位时间为1/9600 = 104us左右。
104/16 = 6.5us (一个CLK时间,具体根据单片机频率调整可以5 - 7us之间)。
当有数据发送时 开启定时器,先发送起始位,在发送数据位,最后停止位。
发送数据1时将IO口拉低保持104us,
发送数据0时,先将io拉低7个CLK(45us),在拉高保持3个CLK(19us),然后拉低保持6个CLK(39)。(16个CLK 104us)
发送数据代码(硬菜)如下:

void io_uart_SendOneByte(uc ucData)
{uc ucBit;/* start send data  */io_uart.ucTxBuff = ucData;io_uart.ucTxStart = 1;io_uart.ucTxBitCnt = 0;GPIO_ResetBits(IO_UART_TX_PORT, IO_UART_TX_PIN);GPIO_EXTI_Close(IO_UART_RX_PORT, IO_UART_RX_PIN);  //外部中断关闭while((io_uart.ucTxStart == 1) && (io_uart.ucRxStart != 1) )    //if (io_uart.ucTxStart && (io_uart.ucRxStart != 1)){          /* 起始位 */if(io_uart.ucTxBitCnt == 0){ucBit = 0;}/* 停止位 */else if(io_uart.ucTxBitCnt == 9){ucBit = 1;}/* 数据位 */else{ucBit = (io_uart.ucTxBuff >> (io_uart.ucTxBitCnt - 1)) & 0x01;}/* 发送数据0 */if(ucBit == 0){TicksDelayUs(40);IO_UART_TX_PORT->DSET = IO_UART_TX_PIN;/* send data keep 3/16 high pulse */TicksDelayUs(13);//13IO_UART_TX_PORT->DRESET = IO_UART_TX_PIN;TicksDelayUs(33);io_uart.ucTxBitCnt++;}/* 发送数据1 */else{GPIO_ResetBits(IO_UART_TX_PORT, IO_UART_TX_PIN);TicksDelayUs(92);io_uart.ucTxBitCnt++;}if(io_uart.ucTxBitCnt == 10){io_uart.ucTxBitCnt = 0;io_uart.ucTxStart = 0;GPIO_EXTI_Init( IO_UART_RX_PORT, IO_UART_RX_PIN, EXTI_FALLING);    //PF5输入中断打开}}
}

接下来讲数据接收:
接收数据相对简单,用到单片机io口外部中断加 定时器
数据接收io默认为高电平,数据0为3 / 16 脉冲。
接受步骤:
一个字节接收缓冲,默认赋值 0xff,设置定时器100us中断,io口当检测到下降沿中断时 (起始位),开启定时器 并开始数据接收,当接收到数据0时,把当前接收位置0,定时器中断8周期之后1字节数据接收结束:
接收代码如下:

/* io uart rx start interrupt */
void GPIO_IRQHandler(void)
{uc ucBit;if(SET == GPIO_EXTI_EXTIxIF_ChkEx(IO_UART_RX_PORT, IO_UART_RX_PIN)){GPIO_EXTI_EXTIxIF_ClrEx(IO_UART_RX_PORT, IO_UART_RX_PIN);/* receive start bit start receive! */if((io_uart.ucRxStart == 0) && (io_uart.ucTxStart == 0)){io_uart_StartReceive();}else if(io_uart.ucRxStart){/* receive zero  bit 0 - 7位*/io_uart.ucRxBitCnt = io_uart.usRxTimeBase;//数据位io_uart.ucRxBuff &= ~(0x01 << io_uart.ucRxBitCnt);/* 接收完一个字节 */if(io_uart.ucRxBitCnt >= 7){if(Uart_Ring_Buff[0].usLen < UART_BUFF_SIZE){Uart_Ring_Buff[0].ucBuff[Uart_Ring_Buff[0].usTail] = io_uart.ucRxBuff;Uart_Ring_Buff[0].usTail = (Uart_Ring_Buff[0].usTail + 1) % UART_BUFF_SIZE;Uart_Ring_Buff[0].usLen++;}io_uart.ucRxBitCnt = 0;io_uart.ucRxStart = 0;ETIMx_ETxCR_CEN_Setable(ETIM1, DISABLE);  //停止定时器io_uart.usRxTimeBase = 0;}}}
}

定时器中断代码:

void ETIM1_IRQHandler(void)
{   if(SET == ETIMx_ETxIF_OVIF_Chk(ETIM1)){ETIMx_ETxIF_OVIF_Clr(ETIM1);if(io_uart.ucRxStart){/* 定时器位计时标记,当数据为0XFF及最后一个字节判断 */if(++io_uart.usRxTimeBase >= 8){if(Uart_Ring_Buff[0].usLen < UART_BUFF_SIZE){Uart_Ring_Buff[0].ucBuff[Uart_Ring_Buff[0].usTail] = io_uart.ucRxBuff;Uart_Ring_Buff[0].usTail = (Uart_Ring_Buff[0].usTail + 1) % UART_BUFF_SIZE;Uart_Ring_Buff[0].usLen++;}io_uart.ucRxBitCnt = 0;io_uart.ucRxStart = 0;ETIMx_ETxCR_CEN_Setable(ETIM1, DISABLE);    //停止定时器io_uart.usRxTimeBase = 0;}}}
}
如有考虑不周的地方,请多指教,欢迎大家讨论,谢谢!

国产单片机IO口模拟IrDA1.0协议相关推荐

  1. 单片机IO口模拟串口程序(发送+接收

    单片机IO口模拟串口程序(发送+接收)[转] qcmc 发表于 - 2011-6-23 0:42:00 前一阵一直在做单片机的程序,由于串口不够,需要用IO口来模拟出一个串口.经过若干曲折并参考了一些 ...

  2. 串口发送程序linux,单片机IO口模拟串口程序(发送+接收

    前一阵一直在做单片机的程序,由于串口不够,需要用IO口来模拟出一个串口.经过若干曲折并参考了一些现有的资料,基本上完成了.现在将完整的测试程序,以及其中一些需要总结的部分贴出来. 程序硬件平台:11. ...

  3. 20120726-分析解决“STM8L101单片机IO口模拟串口通讯发生的奇怪现象”

    近日因工作关系,需要用STM8L101F3P6这款单片机用IO口模拟串行通讯,波特率2400bps,前辈同事已经写完了程序,我需要拿来研究一下该款MCU的低功耗的情况,而在调试的过程中,发现1个奇怪的 ...

  4. 芯圣SQ013单片机IO口模拟串口 延时法

    因为懒,许久未来更新,不过学习还是没有停止.今天我们介绍用芯圣SQ013模拟串口. 串口通讯概述 我们常用的串口通讯协议 为1个起始位+8个数据位+1位结束位.起始位为低电平,结束位高电平.一般我们常 ...

  5. linux下I2C驱动发送IO时序,笔记四:linux下IO口模拟实现I2C协议

    一.i2c总线是什么? 1.i2c总线是一种物理总线及实实在在的总线,通过板子pcb等图能看到. 2.i2c总线是一种主从结构. 3.i2c总线是一种通信协议. 4.i2c总线是两线制半双工串行总线: ...

  6. 使用C语言编写DTMF检测程序,单片机IO口模拟DTMF信号的实践问题

    自己顶顶~ 我把问题简单化下,不谈自己的实践,网上有个 "双龙DTMF演示程序的两点疑问,做过DTMF(软件PWM方法)的请进"的帖子,我是看了这个帖子去动手实践的,实例代码如下 ...

  7. 单片机IO口模拟SPI四种模式的程序

    2013年09月21日 10:00:02 zyboy2000 阅读数:23924 #include "iom8535v.h" #define _CPOL 1 #define _CP ...

  8. STM32 IO口模拟ISO7816(PSAM卡)协议

    单片机:stm32f103c8t6   实现方式:纯IO口模拟(RST.I/O.CLK均为普通IO口) 实现功能:接触式CPU卡.PSAM.SIM读(写) 网上有很多相关的代码,有的是用自带的智能卡接 ...

  9. STC15单片机读写大容量SD卡(IO口模拟SPI模式)

    使用的芯片是STC15系列的IAP15F2K61S2,开发板是51的xl2000.把芯片座上的51芯片拔掉换成STC的,混合模式.(配置够低吧) 源码由51开发板例程的实验26修改而来. 浏览了网上的 ...

最新文章

  1. 如何高效搜索汪子熙公众号发表的文章
  2. python send 案例_python使用rabbitmq实例三,交换机
  3. 安卓窗口动画修改制作心得
  4. java tempfile read_Java资源作为文件
  5. 图像处理-STB图片读写
  6. 无人驾驶飞机来了!空难后波音的电动飞机你敢乘吗?
  7. AWS服务器可以设置虚拟ip吗,《AWS云计算实战》3.使用虚拟服务器:EC2
  8. canon l11121e驱动_佳能打印机l11121e驱动下载
  9. 200元组群晖—HP惠普T610瘦客户端:直接硬盘启动黑群晖
  10. ACM/IOI 历年国家集训队论文集和论文算法分类整理
  11. 你想要的英雄联盟人物模型素材,这里都能找到
  12. Qt模仿QQ登录界面(一)
  13. 计算机机械硬盘系统安装,电脑硬盘安装图解,机械硬盘安装-
  14. 用Altium designer画PCB的一般心得
  15. 对网页 ‘’为所欲为‘’ 之手动实现 csdn深色模式?
  16. c#取消word修订痕迹_法律人必备的WORD技能,从1.0到2.0丨星瀚技术派
  17. 使用HybridSN进行高光谱图像分类
  18. 打开计算机任务栏有桌面没,开机后桌面没有图标任务栏无显示怎么解决
  19. Node.js + Web Socket 打造即时聊天程序嗨聊(1)
  20. 话生态 | F-One联手思凯普,靠谱!

热门文章

  1. 手机射频测试总结(五)——蓝牙部分
  2. 网络测试工具 iperf 使用指南
  3. 李阳疯狂英语·超级人生名言20句
  4. 解剖常用软件程序都用什么语言开发
  5. 机器学习 - 如何理解激活函数和增益值的关系
  6. 广州iOS培训之免费参加啦
  7. 【图像处理】图像直方图+滤波+小波变换+分割处理系统【含GUI Matlab源码 608期】
  8. Erlang和Ruby近况:Vertebra,Fuzed,Github
  9. MATLAB透镜成像特征曲线及分析(二)
  10. 百变大侦探剧本杀开启新玩法!等你一本正经胡说八“倒”