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

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

IrDA1.0协议是一种利用红外通信的无线传输协议,可以很好的解决一些便携式设备与主机之间通信的问题,具有携带方便,低功耗,成本低,传输可靠等特点,缺点是传输距离较短,速率较慢最高支持(115200波特率)。
此处的irda1.0协议并不是遥控器编解码协议,两者之间编解码方式不一样。国外很多单片机都自带了串口转IrDA1.0的编解码功能,但最近因为换方案,原因找了很多国内单片机都不带IrDA编解码功能,所以在这里为大家提供一个io口模拟IrDA的方案。(原理和串口一样)
单片机使用的是 复旦微的FM33G0XX单片机,红外收发器为 TFBS4652,波特率为9600。
!
图片描述了 正常串口数据调制为IrDA收发的波形
图片描述了普通串口调制解调 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);//13
			IO_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;
			}
		}
	}
}
如有考虑不周的地方,请多指教,欢迎大家讨论,谢谢!
CH340 USB转串、USB转打印解决方案概述: 该设计方案CH340的USB转串、USB转打印、USB转IrDA的原理图和PCB,串含DB9的RS232、低成本RS232、TTL的UART等各种版本,打印含DB36连接器、DB25插孔两种版本,USB红外适配器、USB转IrDA含6脚、8脚红外收发器两种,可用于OEM产品制造商。 附件内容截图: CH340简述: CH340是一个USB 总线的转接芯片,实现USB转串或者USB转打印。在串方式下,CH340提供常用的MODEM联络信号,用于为计算机扩展异步串,或者将普通的串设备直接升级到USB总线。有关USB转打印的说明请参考手册(二)CH340DS2。 CH340特 点: > 全速USB 设备接,兼容USB V2.0。 > 仿真标准串,用于升级原串外围设备,或者通过USB增加额外串。 > 计算机端Windows 操作系统下的串应用程序完全兼容,无需修改。 > 硬件全双工串,内置收发缓冲区,支持通讯波特率50bps~2Mbps。 > 支持常用的MODEM 联络信号RTS、DTR、DCD、RI、DSR、CTS。 > 通过外加电平转换器件,提供RS232、RS485、RS422 等接。 > CH340R 芯片支持IrDA 规范SIR红外线通讯,支持波特率2400bps到115200bps。 > 软件兼容CH341,可以直接使用CH341的驱动程序。 > 支持5V 电源电压和3.3V电源电压甚至3V 电源电压。 > CH340C、CH340E 和CH340B 内置时钟,无需外部晶振,CH340B 还内置EEPROM 用于配置序列号等。 > 提供SOP-16 和SSOP-20以及MSOP-10无铅封装,兼容RoHS。 型号区别: CH340C和CH340E以及CH340B内置时钟,无需外部晶振。 CH340B还内置EEPROM用于配置序列号,以及部分功能可定制等。 CH340R 内置简易RS232,无需外部RS232转换芯片,暂无现货。 所有附件内容如下: 技术手册:CH340DS1.PDF; 驱动程序: 1、CH341SER.EXE(Windows系统,包含WIN10 -32/64位); 2、 CH341SER_ANDROID.ZIP(安卓免驱应用库API); 3、 CH341SER_LINUX.ZIP(Liunx系统) 4、 CH341SER_MAC.ZIP (苹果MAC OS) 原理图/PCB: CH340PCB.ZIP
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值