GPIO模拟串口



//串口
#define TXD   P54D         //端口
volatile unsigned char tx;//数据
volatile unsigned char txb;//数据位数
volatile unsigned char txsend;//要求发送,遇到1 进行发送一次 发送结束 0




//p54端口发送  
/*
波特率4800 =》  4800bit(位)每秒 =>480字符每秒
1起始位  8数据位 1停止位  共10bit  
1000 000 /4800 =208.333us  则1bit的电平持续时间是208us 一个字符则需要2.08ms
起始位是低电平,停止位是高电平  则待机状态高电平   低位先发

*/
//串口发送数据
void usart_sent(void)//每次中断进入该函数是208us    
{
	if(!star)//未发送起始位
	{
		star=1;
		TXD=0;
	}
	else//已发送起始位
	{
		if(!stop)//未发送停止位   处于发送数据位期间
		{
			if(tx&(0x01<<txb))//发送数据
			{
				TXD=1;//高电平
			}
			else
			{
				TXD=0;//低电平
			}
			txb++;//前面位数是txb  0-7 
			if(txb>=8)//发送完数据完成  完成 txb是7  +1后是8  结束数据位的发送
			{
				txb=0;
				stop=1;//进行发送停止位
			}

		}
		else
		{
			stop=0;
			star=0;
			TXD=1;//停止位是高电平
			txsend=0;//发送结束后才能  不再进入txsend==5中,在进行txsend++计时
		}
	}
	
	
}


void main(void)
{

    TXD=1;
	txb=0;
	stop=0;
	star=0;
    txsend=1;
    //只需要修改发送的数据就可以了
	tx=0x91;
    
}



void int_isr(void) __interrupt
{
   	__asm 
   	push
   	__endasm;
   	
   	//************需要放在208us中断中使用   对应设置波特率是4800
    //我现在使用是104us   所以在计时上需要104*2
   	//当T0CNT递减到0时,此时产生T0溢出中断请求标志T0IF/T1IF置1 
   	if(T0IF)   //104us触发一次
   	{      	
   	   	T0IF=0; 
		T0CNT=0x9A;
		timer0us_4++;
		if(timer0us_4>=2)//104us*2
	    {
		   timer0us_4=0;
	
		   if(txsend==5)//设置间隔发送时间
		   {
			  usart_sent();
		   }
		   else
		   {
			   txsend++;
		   }
		   
	    }
   	}      
   	
   	
   	if(T1IF)   //32uS
   	{      	
   	   	T1IF=0; 
   	   	timer1us=1;
		timer1ms_1++;
		
   	}
   	

   	__asm 
   	pop
   	__endasm;
}

使用定时器设置模拟串口发送功能,波特率是4800 ,需要配合208us定时器中断使用

#define  RXD   P15D     //接受端口
volatile unsigned char  rx;//数据位
volatile unsigned char  rxbtime;//位数计时
volatile unsigned char  rxb;//数据位数
volatile unsigned char  stop;//空闲状态
volatile unsigned char  key_val;//数据位主程序进行判断


//52us触发一次
//串口数据接收
void usart_accept(void)
{
	
	//空闲状态。端口持续高电平
	if(stop==1)
	{
		
		if(RXD==0)//一直等待发送端的起始信号,低电平
		{
			rxbtime=2;//在低电平的208us中需要在104us中再检测一次
			rxb=0;//数据位0,发送端是低位先传
			stop=0;//传输状态
			
			
		}
	}
	else
	{
		if(rxbtime<=1)//延时计算时间
		{
				
				switch(rxb)
				{
					case 0://起始电平经过2*52=104us
					
					if(RXD)//检测起始位是否真启动,
					{
						//起始位错误
						stop=1;
						rxb=0;
					}
					else
					{
						//延时208us进行检测   由于第一次起始位是在104us后续的208us都是
                        //在波形的中间检测,避免了临界有误差
						rxbtime=4;
						rxb++;
					}
					break;
					
					case 1:
					case 2:
					case 3:
					case 4:
					case 5:
					case 6:
					case 7:
					case 8:
					//先接收低位  右移7次  最后一次不需要右移  触发8次
					rx=rx>>1;//当第一次rx=0是是无效的,下面才给0位赋值,
					if(RXD)
					{
						rx=rx|0x80;
					}
					rxb++;
					rxbtime=4;//延时208us进行检测
					break;
					
					case 9:
					if(RXD)//等待停止位
					{
						
						stop=1;
						rxb=0;
						key_val=rx;
					}
					break;
					
				}
			
		}
		else
		{
			rxbtime--;
		}
	
	}
	
	
}


void main (void)
{    
   
    stop=1;
  
   
   
   	while(1)
   	{  
        switch(key_val)
	    {
		    case 0xF0://按照发送端对应的码接受就可以了
		   .....//需要执行的命令
		    break;
		
	    	case 0xF1:
		   ....
		    break;
		
		    case 0xF2:
		   ...
		    break;
		
		    case 0xF3:
		  .....
		     break;
		
		    case 0xF4:
		  .....
		    break;
		
		    case 0xF5:
		  .....
		    break;
		
		
	    }
	    key_val=0;


   	} 



   	
}

void int_isr(void)__interrupt
{

    if((T0IF)&&(T0IE))//52us
    {
   	   	T0CNT=151;
   	   	T0IF=0;
   	   	F_52us=1;
        //每次进入52us定时器
   	   	usart_accept();
    }
   	
   	
   	if((T1IF)&&(T1IE))//32us
   	{
   	   	T1CNT=255;
   	   	T1IF=0;
   	 
   	   
   	}

}






使用定时器设置模拟串口接受功能,波特率是4800 ,需要配合52us定时器中断使用

上方发送端使用芯片是晟矽微7041, 接收端使用芯片是晟矽微6060,可以成功实现,

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值