上个月入职了一家做消费类电子的公司,做了两个小项目,用的是NY8芯片,资源有限,没有串口和IIC,其中一个项目是做闹钟显示板,只用将主机发过来来命令处理就行,做的是通版,使用串口和IIC两种方式数据。
网上搜寻一边,参考借鉴了整理出一份可行的方案,整理出来供以后工作和有需要的朋友使用。
下面是h文件
#ifndef SoftWareSeries
#define SoftWareSeries
#include "user.h"
#include "display.h"
#define BaudRate 10 //bps9600 10 4800 20
#define RXDBit Port_B7
#define TXDBit Port_C0
#define IO_RXD PORTBbits.PB7
#define IO_TXD PORTCbits.PC0
enum {
COM_START_BIT,
COM_D0_BIT,
COM_D1_BIT,
COM_D2_BIT,
COM_D3_BIT,
COM_D4_BIT,
COM_D5_BIT,
COM_D6_BIT,
COM_D7_BIT,
COM_STOP_BIT,
};
extern U8 RXD_BIT;
extern U8 RXD_DATA;
void SoftWareUartInit(void);
void TXD_OneByte(U8 Data);
void UART_Send(U8 *Buffer,U8 Length);
#endif
U8 RXD_BIT = COM_STOP_BIT;
U8 RXD_DATA = 0;
发送部分
关闭中断使用delay_us模拟uart时序进行发送
void SoftWareUartInit(void)
{
IOSTB |= RXDBit; //置1 输入
IOSTC &= ~TXDBit; //置0 输出
BPHCON &= ~RXDBit; //置0使能上拉
IO_TXD = 1; //拉高发送位
}
void TXD_OneByte(U8 Data)
{
U8 i;
IO_TXD = 0; //拉低发送起位
delay_10us(BaudRate); //100us bps9600
for(i = 0;i<8;i++)
{
if(Data&0x01) IO_TXD = 1; //发送1bit数据,低位先发
else IO_TXD = 0;
delay_10us(BaudRate);
Data = Data>>1; //右移发送下一bit
}
IO_TXD = 1; // 拉高发送停止位
delay_10us(BaudRate);
}
/*
function IO模拟串口发送数据包
parameter Buffer 数据包的首地址
Length 数据包的长度
*/
void UART_Send(U8 *Buffer,U8 Length)
{
U8 t;
DISI();//关闭中断,数组处理
for(t = 0;t<Length;t++)
{
TXD_OneByte(Buffer[t]);
}
ENI();//打开中断
}
接收部分
接收采用的是外部中断+定时器中断的方式,UART数据帧起始bit是高电平拉低,触发外部中断之后开启定时器,定时器按bps中断读取IO口电平
外部中断开始一帧数据接收,接收位置赋值起始位,中间delay是为了定时器中断触发时检测的是中间电平而不是边缘电平。
if(INTFbits.PABIF){ ///PAB转换中断
INTFbits.PABIF = 0;
if(0==IO_RXD){ //检测引脚高低电平,如果是低电平,则说明检测到下升沿
if(COM_STOP_BIT == RXD_BIT){
flag.RXDStart = 1;
Count_2ms = 0; //RXD接收开始 计时清0
RXD_BIT = COM_START_BIT;
delay_10us(3); //延时30us时间,每次中断采样到中间的电平,而不是边缘
TIMER3_CMD(ENABLE);
}
}
}
定时器中断模拟uart接收时序,定时时长104us(9600bps),项目接收第一个字节的数据是数据长度
if(INTE2bits.T3IF){
INTE2bits.T3IF = 0;
RXD_BIT++;
if(COM_STOP_BIT == RXD_BIT){
TIMER3_CMD(DISABLE); //一byte数据接收完成,关闭定时器
ReciveData[ProcessTimes]=RXD_DATA;
if(0==ProcessTimes) DataLength=ReciveData[ProcessTimes]; //数据包长度赋值
else if(DataLength==ProcessTimes){
flag.RXDStart = 0; //接收结束 接收标志位置0
flag.UartRecived = 1; //接收完成标志位,实际多接收了一个byte校验数据
Count_2ms = 0; //传输完一次数据包 计时清0
}
ProcessTimes++;
return;
}
if(1==IO_RXD) RXD_DATA |= (1 << (RXD_BIT - 1)); //接收一个bit
else RXD_DATA &= ~(1 << (RXD_BIT - 1));
}
来源:CSDN
作者:蜜汁辣酱^_^
链接:https://blog.csdn.net/lala0903/article/details/103484705