• GPIO模拟UART串口时序


    GPIO模拟UART串口时序

    模拟时序:

    平台:Cortex-M0

    与FPGA UART的区别:

      FPGA发送、接收使用的是独立的时序,并行处理易于实现。而单片机只能使用定时器来模拟时序,并通过外部下降沿中断触发启动,实时性受到限制;对于实时性要求较高的应用,需要同时处理发送和接收时(全双工)1路UART需要使用2个定时器;而半双工应用可以只使用一个定时器即可实现。基于50MHZ的M0一般9600是可以实现的,在向上估计会不稳定。主要是应用于对于特定设计临时增加低速串口通信,降低成本。

    示例代码:

    V1.5:双定时器方案

    1、myiouart.h+ myiouart.c

    2、资源占用:1个输入中断+2个定时器(针对实时要求高的场合)

    myiouart.h:
    //<<< Use Configuration Wizard in Context Menu >>>
    #ifndef _MYIOUART_H_
    #define _MYIOUART_H_
    #include "LPC11xx.h"
    
    //<h> MyIouartConfig [2017.2.20]
    //<i>   注:双定时器模拟串口!CT32B0+CT32B1
    	//<o>ECHO <0=> No <1=> Yes
    	//<i>回显测试功能: 
    	//<i>打开回显功能后,模拟串口将自动返回自己所接收到的数据,仅作测试串口功能使用!
    	#define ENABLE_ECHO 	0					 
    
    	//<o> COM_BAUDRATE <1200=> 1200 <9600=> 9600  <57600=> 57600  <115200=> 115200
    	//<i> 串口通讯波特率配置
    	//<i> 默认为9600!
    	#define IOUART_BAUDRATE	9600
    
    
    //</h>
    
    
    //--------------------------------------------------------------
    #define IOUART_RECV_NULL 0         //没有接收数据
    #define IOUART_RECV_OK 1           //接收数据成功返回值
    #define IOUART_RECV_WRONG_ST 11    //接收数据起始位出错返回值
    #define IOUART_RECV_WRONG_EN 12    //接收数据结束位出错返回值
    
    //
    #define   SET_UART_BAUD   48000000UL/(IOUART_BAUDRATE) //波特率设置
    #define   MyUart_STOPBITS 1
    
    
    
    //
    
    //config  iouart3
    #define  MyIOUART_TX_PORT      PIO2_8
    #define  MyIOUART_RX_PORT      PIO2_7
    #define  MyIOUART_TX_P         LPC_GPIO2
    #define  MyIOUART_RX_P         LPC_GPIO2
    #define  MyIOUART_TX_P_INDEX   8
    #define  MyIOUART_RX_P_INDEX   7
    //
    #define  MyIOUART_RX_IRQn   EINT2_IRQn
    
    
    //------------------------------------------
    
    extern char g_strtemp[32];	
    extern unsigned long g_rx_cnt;//For Debug. Record the count value of recieved bytes!
    extern unsigned long g_tx_cnt;//For Debug. Record the count value of sended bytes!
    
    
    //
    #define BUFFER_LEN 128
    
    //
    char* NumToStrEx(long Number,char*PStr,unsigned char Len);
    //FIFO Buffer
    void Iouart_FifoInit(void);
    unsigned char GetLen_RecvedData(void);
    unsigned char* GetTxbuf_RecvedData(void);
    unsigned char ReadByte_RxFiFo(void);
    int WriteByte_TxFifo(unsigned char *T,unsigned char len);//非阻塞
    
    //
    void put_char(char *cp);//阻塞
    void iouart1_send(char *pData,unsigned char pLen);//阻塞
    void print_dat(char sp[],char len);//阻塞
    //
    void IOUART1_Init(void);
    
    void Timer2Init(void);
    void Timer3Init(void);
    
    
    
    
    
    //--------------------------------------------------------------
    #endif
    // <<< end of configuration section >>>
    
    
    myiouart.c:
    
    #include "myiouart.h"
    //
    char g_strtemp[32]={0};	
    unsigned long g_rx_cnt = 0;//For Debug. Record the count value of recieved bytes!
    unsigned long g_tx_cnt = 0;//For Debug. Record the count value of sended bytes!
    
    //RX
    static volatile unsigned char l_recv_byte=0;
    static volatile unsigned char l_recv_st=0;
    static volatile unsigned char l_recv_cnt=8;
    
    //TX
    static volatile unsigned char l_send_byte=0;
    static volatile unsigned char l_send_st=0;
    static volatile unsigned char l_send_cnt=8;
    static volatile unsigned char l_send_style=0;//根据send_style判断是通过缓存发送还是直接发送
    
    //
    static volatile unsigned char l_channel=0;
    //
    //l=local g=global  
    //FIFO Buffer
    unsigned char l_Txbuffer[8+BUFFER_LEN]={0};
    volatile unsigned char l_Rxbuffer[8+BUFFER_LEN]={0};
    volatile unsigned char l_RxDataLen=0;
    volatile unsigned char l_RxWrongRecord[2+BUFFER_LEN]={0};//接收数据出错记录BUFFER
    //
    void Iouart_FifoInit(void)
    {
    	//仅记录一个BUFFER_LEN长度的接收错误记录
    	l_RxWrongRecord[0]=2;//sp:2->(2+BUFFER_LEN)-1
    	l_RxWrongRecord[1]=(2+BUFFER_LEN)-1;//end addr
    	//
    	l_RxDataLen=0;
    	
    	//Rx
    	//接收数据的起始地址(使用相对地址从8->BUFFER_LEN-1)
    	l_Rxbuffer[0]=8;
    	l_Rxbuffer[1]=0;
      //接收数据的结束地址
    	l_Rxbuffer[2]=8;
    	l_Rxbuffer[3]=0;
    	//Buffer的结束地址
      l_Rxbuffer[4]=(BUFFER_LEN-1)+8;
    	l_Rxbuffer[5]=0;
    	//接收数据的长度
    	l_Rxbuffer[6]=0;
    	//Buffer的长度
    	l_Rxbuffer[7]=BUFFER_LEN;
    	
    	//Tx
    	//Tx数据的起始地址
    	l_Txbuffer[0]=8;
    	l_Txbuffer[1]=0;
      //Tx数据的结束地址
    	l_Txbuffer[2]=8;
    	l_Txbuffer[3]=0;
    	//Buffer的结束地址
      l_Txbuffer[4]=(BUFFER_LEN-1)+8;
    	l_Txbuffer[5]=0;
    	//Tx数据的长度
    	l_Txbuffer[6]=0;
    	//Buffer的长度
    	l_Txbuffer[7]=BUFFER_LEN;
    	
    }
    
    /*
    获取Buffer中接收到的数据长度
    */
    unsigned char GetLen_RecvedData(void)
    {
       return l_RxDataLen;
    }
    
    unsigned char* GetTxbuf_RecvedData(void)
    {
       return l_Txbuffer;
    }
    /*
     从模拟串口读取一个字节数据 
     调用该函数前先判断GetRecvDataLen()返回值,否则在没有接收到数据时读到的数据为0
    */
    unsigned char ReadByte_RxFiFo(void)
    {
    	unsigned char Data0=0;
    	if(l_Rxbuffer[6])
    	{
    		 Data0 = l_Rxbuffer[l_Rxbuffer[0]];
    		 //
    		 if(l_Rxbuffer[0]< l_Txbuffer[4])
    		 {
    		   l_Rxbuffer[0]++;
    		 }
    		 else
    		 {
    			 l_Rxbuffer[0]=8;
    		 }
    		 //
    		 l_Rxbuffer[6]--;
    	}
      //update rx len
    	l_RxDataLen=l_Rxbuffer[6];
    	
      return Data0;
    }
    
    /*
     从模拟串口发送一个数据Buffer,属于一次性连续发送!
     若发送缓冲区满返回-1
    */
    int WriteByte_TxFifo(unsigned char *T,unsigned char len)
    {
      unsigned char i = 0;
    	if(len)
    	while(len--){
    	if(l_Txbuffer[6] < l_Txbuffer[7]) {
         l_Txbuffer[6]++;//TxLength
    		 l_Txbuffer[l_Txbuffer[2]]=T[i++];
    		 if(l_Txbuffer[2]<l_Txbuffer[4])
    		 {
    			 l_Txbuffer[2]++;
    		 }
    		 else
    		 {
    			 l_Txbuffer[2]=8;
    		 }
    	 }
    	 else
       {
         return -1;//发送缓冲区满
       }	
    	}
    		 
    	 //开启发送需设置5个变量
    	 l_send_byte = l_Txbuffer[l_Txbuffer[0]];
    	 l_send_cnt = 9;
    	 l_send_style=1;	
       LPC_TMR32B0->TCR = 1;
    	 l_send_st=1;
    
       //-----------
       return 1;
    	
    }
    
    
    
    /*
      数字转字符串函数
    */
    char* NumToStrEx(long Number,char*PStr,unsigned char Len)
    {
    	unsigned long NumberT=0;
    	unsigned char Count=0;
    	if(Number<0)  
    	{
    		*PStr='-';
    		Number=-Number;
    		Count=1;
    	}
    	else if(Number==0)
    	{
    	  *PStr='0';
    		*(PStr+1)=0;
    		return PStr;
    	}
    	NumberT=Number;
    	while(NumberT)
    	{
    	   	 NumberT/=10;
    		 Count++;
    	}
    	if(Len<=Count)  return 0;
    	//
    	*(PStr+Count--)=0;
    	//
    	while(Number)
    	{
    		*(PStr+Count--)='0'+Number%10;
    		Number/=10;
    	}
    	return PStr;
    }
    
    void put_char(char *cp)
    {
        //LPC_GPIO2->IE &= ~(1<<7);LPC_GPIO2->IC=(1<<7); //NVIC_DisableIRQ(EINT2_IRQn);
    	  //LPC_GPIO3->IE &= ~(1<<1);LPC_GPIO3->IC=(1<<1);
    	  //---------------------------------------------
      	
    		l_send_byte = *cp;	
    		l_send_cnt = 9;
    		l_send_style = 0;
      	l_send_st=1;
    		// LPC_TMR16B1->TCR = 1;//start counter 
    	  LPC_TMR32B0->TCR = 1;//根据使用的定时器选择
    		while(l_send_st){}
    
    	  //--------------------------------------------
    	
    	  //LPC_GPIO2->IE |= (1<<7);
    	  //NVIC_EnableIRQ(EINT2_IRQn); 
    	  //LPC_GPIO3->IE |= (1<<1);
    
    }
    
    
    /*
        阻塞发送字符串,不使用缓存
    */
    void iouart1_send(char *pData,unsigned char pLen)
    {
    	while(pLen--)
    	{
    		put_char(pData++);
    	}
    }
    
    /*
        阻塞发送数据,不使用缓存
    */
    void print_dat(char sp[],char len)
    {
      LPC_GPIO0->DATA |= (1 << 7);//H	485TxMode
    	//-----------------------------------------
    	while(len--)
    	{
    		put_char(sp++);
    	}
    	//-----------------------------------------
    	LPC_GPIO0->DATA &= ~(1 << 7);	//L	485RxMode	
    }
    
    
    void IOUART1_Init(void)
    {
    	Iouart_FifoInit();
    	//
    	LPC_SYSCON->SYSAHBCLKCTRL |= (1ul << 6); 
    	//UART3 [channel=0] & 4852  EN--P0.7   RX--P2.7  TX--P2.8 
    	//TX PIO2_8
    	LPC_IOCON->MyIOUART_TX_PORT &= ~(0x07);	/*IO功能*/
    	MyIOUART_TX_P->DIR  |= (1 << MyIOUART_TX_P_INDEX);	/*Output*/
    	MyIOUART_TX_P->DATA |= (1 << MyIOUART_TX_P_INDEX);//H	
    	//RX  PIO2_7    
    	LPC_IOCON->MyIOUART_RX_PORT &= ~(0x07);//IO fucntion 
    	MyIOUART_RX_P->DIR &= ~(1<<MyIOUART_RX_P_INDEX);//Input
    	MyIOUART_RX_P->IS  &= ~(1<<MyIOUART_RX_P_INDEX);//edge sensitive
    	MyIOUART_RX_P->IEV &= ~(1<<MyIOUART_RX_P_INDEX);//falling edge 
    	MyIOUART_RX_P->IBE &= ~(1<<MyIOUART_RX_P_INDEX);//
    	//
    	NVIC_SetPriority(MyIOUART_RX_IRQn, 0);
    	NVIC_EnableIRQ(MyIOUART_RX_IRQn);
    	MyIOUART_RX_P->IC=(1<<MyIOUART_RX_P_INDEX);
    	MyIOUART_RX_P->IE |= (1<<MyIOUART_RX_P_INDEX);//enable interrupt
    	
    	//sel uart chanel
    	l_channel=0;
    	g_rx_cnt=0;
    	g_tx_cnt=0;
    	
    	//
    	Timer3Init();//CT32B1  For Rx!
    	Timer2Init();//CT32B0  For TX!
    }
    
    
    
    void RecvWrongSt(void)
    {		
    	 //记录错误,并重新开启RX引脚接收中断
    	 LPC_GPIO3->DATA &= ~(1 << 3);//L	
    	 //Record wrong case.Just For Debug.
    	 l_RxWrongRecord[l_RxWrongRecord[0]]=IOUART_RECV_WRONG_ST;
    	 if(l_RxWrongRecord[0]<l_RxWrongRecord[1])
    	 {
    		 l_RxWrongRecord[0]++;
    	 }
    	 //		 
    	 MyIOUART_RX_P->IC |= (1<<MyIOUART_RX_P_INDEX);				 
    	 MyIOUART_RX_P->IE |= (1<<MyIOUART_RX_P_INDEX);
    	 return;		
    }
    
    void  recv_interrupt(void) //Just For Echo!
    {
      //回显测试 
      unsigned char len = l_RxDataLen;	
    	while(len--)
    	{
        unsigned char t= ReadByte_RxFiFo();
        WriteByte_TxFifo(&t,1);
      }  
    }
    
    
    
    void PIOINT2_IRQHandler(void)//下降沿触发中断
    {
      LPC_GPIO3->DATA |= (1 << 3);//H  //LED
    	//
    	if((MyIOUART_RX_P->DATA & (1<<MyIOUART_RX_P_INDEX)))//起始位电平(L)检测
    	{
    	  RecvWrongSt();
        return;
    	}
    	//
    	if(MyIOUART_RX_P->MIS&(1<<MyIOUART_RX_P_INDEX))//Rx 判断触发中断的引脚
    	{		 
           //
    		   MyIOUART_RX_P->IE &= ~(1<<MyIOUART_RX_P_INDEX);//disable interrupt
    	     MyIOUART_RX_P->IC |= (1<<MyIOUART_RX_P_INDEX);//clear interrupt flag
    		   //
    		   //
    		   l_RxDataLen = 0;//接收过程禁止读取数据
    		   l_recv_cnt = 8;
    			 l_recv_st = 1;
    		   // start recv
           LPC_TMR32B1->TCR = 1;
    			 LPC_TMR32B1->IR = 1;
    			
    			 //
    			 //LPC_GPIO2->IC=(1<<7);//clear interrupt flag
    			 //LPC_GPIO2->IE |= (1<<7);//enable interrupt
    			 //NVIC_EnableIRQ(EINT2_IRQn);
    			 //
    	 }
    	 //
       LPC_GPIO3->DATA &= ~(1 << 3);//L	
    }
    
    
    //32位定时器  CT32B0/1  【注:32位定时器和16位定时器功能一样,仅仅将16改成32,并修改一下时钟使能位(C32B0=9;C32B1=10),即可】
    void Timer2Init(void)//CT32B0
    {
      LPC_SYSCON->SYSAHBCLKCTRL	|= (1<<9); //enable ct32b1 clk 
      LPC_TMR32B0->CTCR &= ~(3);//timer[function sel]
    	LPC_TMR32B0->MCR = 3;//enable interrupt and reset autoself
    	//-------------------------------------------------------------
    	LPC_TMR32B0->PR = 0;//16bits[max=2^16=65536]  48MHZ(sysahbclk)/48=1000KHZ
    	//IOuart要支持高的波特率,PR值要设置尽量小,然后不断调试MR0的值即可达要想要的波特率,一开始
    	//调试不成功就是因为PR设为了100太大,导致9600接收总是失败
    	//-------------------------------------------------------------
    	//One timer can gennerate four interrupts for MR0、MR1、MR2、MR3.
    	LPC_TMR32B0->MR0 = SET_UART_BAUD;
    	//--------------------------------------------------------------
    	LPC_TMR32B0->TCR = 2;//reset 
    	LPC_TMR32B0->IR =1;//clear interrupt flag
    	LPC_TMR32B0->TCR = 1;//load cfg of ct16b1
    	//
    	LPC_TMR32B0->TCR =2 ;//reset
    	LPC_TMR32B0->TCR =0 ;//stop counter
    	 
    	//
    	NVIC_EnableIRQ(TIMER_32_0_IRQn);	
        NVIC_SetPriority(TIMER_32_0_IRQn,1);	
    	
    }
    
    void Timer3Init(void)//CT32B1
    {
    	LPC_SYSCON->SYSAHBCLKCTRL	|= (1<<10); //enable ct32b1 clk 
    	LPC_TMR32B1->CTCR &= ~(3);//timer[function sel]
    	LPC_TMR32B1->MCR = 3;//enable interrupt and reset autoself
    	//-------------------------------------------------------------
    	LPC_TMR32B1->PR = 0;//10;//16bits[max=2^16=65536]  48MHZ(sysahbclk)/48=1000KHZ
    	//IOuart要支持高的波特率,PR值要设置尽量小,然后不断调试MR0的值即可达要想要的波特率,一开始
    	//调试不成功就是因为PR设为了100太大,导致9600接收总是失败
    	//-------------------------------------------------------------
    	//One timer can gennerate four interrupts for MR0、MR1、MR2、MR3.
    	LPC_TMR32B1->MR0 = SET_UART_BAUD;
    	//--------------------------------------------------------------
    	LPC_TMR32B1->TCR = 2;//reset 
    	LPC_TMR32B1->IR =1;//clear interrupt flag
    	LPC_TMR32B1->TCR = 1;//load cfg of ct16b1
    	//
    	LPC_TMR32B1->TCR =2 ;//reset
    	LPC_TMR32B1->TCR =0 ;//stop counter
    	//
    	NVIC_EnableIRQ(TIMER_32_1_IRQn);	
    	NVIC_SetPriority(TIMER_32_1_IRQn,1);	
    }
    
    //
    void TIMER32_0_IRQHandler (void)//For send destination.
    {
       
        static unsigned char  tx_k=0;
        //
        unsigned char tx_s2;
    	 
        //
        LPC_GPIO0->DATA &= ~(1 << 3);//L LED
        LPC_TMR32B0->IR =1;//clear interrupt flag
    
      
        //TX
    		if(l_send_st){
    				if(l_send_cnt)
    				{
    						if(l_send_cnt == 9)//start bit
    						{
    								if(l_channel==0)
    								{
    										MyIOUART_TX_P->DATA &= ~(1 << MyIOUART_TX_P_INDEX);//L
    								}
    								else if(l_channel==1)
    								{ }
    								else if(l_channel==2)
    								{ }
    								l_send_cnt=8;
    						}
    						else
    						{
    								switch(l_send_cnt)
    								{
    											case 8:
    													tx_s2=0x01;
    													break;
    											case 7:
    													tx_s2=0x02;
    													break;
    											case 6:
    													tx_s2=0x04;
    													break;
    											case 5:
    													tx_s2=0x08;
    													break;
    											case 4:
    													tx_s2=0x10;
    													break;
    											case 3:
    													tx_s2=0x20;
    													break;
    											case 2:
    													tx_s2=0x40;
    													break;
    											case 1:
    													tx_s2=0x80;tx_k=0;
    													break;
    											default:
    													tx_s2=0x0;
    													break;
    								}
    								//-------------------------------------------------------------
    								if(l_channel==0)
    								{//TX
    										if(!(l_send_byte&tx_s2)) MyIOUART_TX_P->DATA &= ~(1 << MyIOUART_TX_P_INDEX);//L
    										else MyIOUART_TX_P->DATA |= (1 << MyIOUART_TX_P_INDEX);//H
    								}
    								else if(l_channel==1)
    								{ }
    								else if(l_channel==2)
    								{ }
    								//
    								l_send_cnt--;
    						}
    				}
    				else
    				{
    						if(tx_k<=(MyUart_STOPBITS-1)) //1->两位停止位  0->1位停止位
    						{
    								if(l_channel==0)
    								{   MyIOUART_TX_P->DATA |= (1 << MyIOUART_TX_P_INDEX);//H
    								}
    								else if(l_channel==1)
    								{ }
    								else if(l_channel==2)
    								{ }
    								//
    								tx_k++;
    						}
    						else
    						{
    							tx_k=0;l_send_cnt  = 9;
    							if(l_send_style)//如果是FIFO发送
    							{
    									l_send_style=0;
    									//一个字节发送完
    									l_Txbuffer[6]--;
    									if(l_Txbuffer[0]<l_Txbuffer[4])  l_Txbuffer[0]++;
    									else    l_Txbuffer[0]=8;
    									//判断是否继续发送
    									if(l_Txbuffer[6])
    									{//连续发送
    											//restart timer
    											l_send_byte = l_Txbuffer[l_Txbuffer[0]];
    											l_send_cnt  = 9;
    											l_send_st = 1;
    											l_send_style = 1;	
    						
    									}
    									else
    									{
    									  l_send_style = 0;	
                        //修改点1:此处导致出现最后一个字节发送两次!需添加:
    									  l_send_st=0; //reset	
    										//reset timer	
    										LPC_TMR32B0->TCR =2;//[0-stop counter  1-start  2-reset]
    										LPC_TMR32B0->IR = 1;		  
    									
    									}
    							}
    							else
    							{
    								l_send_st=0; //reset	
    								//reset timer	
    								LPC_TMR32B0->TCR =2;//[0-stop counter  1-start  2-reset]
    								LPC_TMR32B0->IR = 1;		  
    							}
    						}
    				}
        }
    
    		//--------------------------------
        LPC_GPIO0->DATA |= (1 << 3);//LED
    }
    
    
    
    
    
    
    //
    void TIMER32_1_IRQHandler (void)//For Receive destination.
    {
        static unsigned char  rx_k=0;
    	  static char  stc_recv_check=0;//静态变量
    		static char  rx_interrupt_flag=0;
    	  //
        unsigned char rx_s1;
        //
        LPC_GPIO0->DATA &= ~(1 << 3);//L LED
        LPC_TMR32B1->IR =1;//clear interrupt flag
       	///////
    		//RX
        if(l_recv_st)
        {
            if(l_recv_cnt)
    				{
    						switch(l_recv_cnt)
    						{
    										case 8:
    														rx_s1=0;l_recv_byte=0;
    												break;
    										case 7:
    														rx_s1=1;
    												break;
    										case 6:
    														rx_s1=2;
    												break;
    										case 5:
    														rx_s1=3;
    												break;
    										case 4:
    														rx_s1=4;
    												break;
    										case 3:
    														rx_s1=5;
    												break;
    										case 2:
    														rx_s1=6;
    												break;
    										case 1:
    														rx_s1=7;rx_k=0;stc_recv_check=0;
    												break;
    										default:
    														rx_s1=0;
    										 break;
    						}
    						//-------------------------------------------------------------
    						if(l_channel==0)
    						{//Rx
    							if(MyIOUART_RX_P->DATA & (1<<MyIOUART_RX_P_INDEX))  l_recv_byte+=(1<<rx_s1);
    						}
    						else if(l_channel==1)
    						{ }
    						else if(l_channel==2)
    						{ }
    						//
    						l_recv_cnt--;
    			 }
    			 else
    			 {
    					  if(rx_k<=(MyUart_STOPBITS-1)) //1->两位停止位  0->1位停止位
    						{
    								if(l_channel==0)
    								{//Rx 
    										if(MyIOUART_RX_P->DATA & (1<<MyIOUART_RX_P_INDEX))//检测停止位(H)判断
    										{  
    										    //stc_recv_check = IOUART_RECV_OK;	 
                            stc_recv_check += 2;	
                            stc_recv_check += rx_k;											
    										}
    										else
    										{ 
        										stc_recv_check +=3;	
    											  //stc_recv_check = IOUART_RECV_WRONG_EN; 
    										}
    								}
    								else if(l_channel==1)
    								{ }
    								else if(l_channel==2)
    							  { }
    								//
    								rx_k++;
    						}
    						else
    						{
    							  rx_k=0;l_recv_cnt = 8;
    							  
    							  if(stc_recv_check <= 5)
    								{
    								  stc_recv_check = IOUART_RECV_OK;	
    								
    								}
    								else
                    {
    								 stc_recv_check = IOUART_RECV_WRONG_EN; 
    								}									
    							
    								switch(stc_recv_check)
    								{
    										case IOUART_RECV_OK://成功接收一个字节
    													g_rx_cnt++;
    										      if(l_Rxbuffer[6] < l_Rxbuffer[7])//RxLength
    													{
    															l_Rxbuffer[6]++;
    															l_Rxbuffer[l_Rxbuffer[2]]=l_recv_byte;
    															if(l_Rxbuffer[2] < l_Rxbuffer[4])
    															{
    																	l_Rxbuffer[2]++;
    															}
    															else
    															{
    																	l_Rxbuffer[2]=8;
    															}
    															//连续接收时要精确控制停止位
    															if(l_channel==0)
    															{
    																	if(MyIOUART_RX_P->DATA & (1<<MyIOUART_RX_P_INDEX))
    																	{
    																			l_recv_st=0; 
    																		  rx_interrupt_flag = 1;//模拟串口的接收中断
    																	}
    																	else//检测到下一字节的起始位
    																	{//连续接收	
    																		  //连续收暂时不改变接收缓冲区的数据长度.//l_RxDataLen = 0;//注:连续接收时读取RX缓存区必须使其返回为0,否则会影响数据的接收!
    																			//l_recv_byte = 0;//必须清零,因为接收的结果是通过叠加的方式获得的
    																			l_recv_cnt = 8;
    																			l_recv_st = 1;
    																	}
    															}
    															else if(l_channel==1)
    															{ }
    															else if(l_channel==2)
    															{ }
    														 
    													}
    													else//接收缓存区满
    													{
    															l_recv_st=0;
    													}
    																									
    													break;
    										case IOUART_RECV_WRONG_EN:
    														 //Record wrong case.Just For Debug.
    														 l_RxWrongRecord[l_RxWrongRecord[0]]=IOUART_RECV_WRONG_EN;
    														 if(l_RxWrongRecord[0]<l_RxWrongRecord[1])
    														 {
    																 l_RxWrongRecord[0]++;
    														 }
    														 //
    														 l_RxWrongRecord[l_RxWrongRecord[0]]=l_recv_byte;
    														 if(l_RxWrongRecord[0]<l_RxWrongRecord[1])
    														 {
    																 l_RxWrongRecord[0]++;
    														 }
    														 //
    	                           l_recv_st=0;
    												 break;
    										default:
    											   l_recv_st=0;
    												 break;
    								}
    								//
    								if(l_recv_st==0)
    								{
    										//开RX引脚中断
    										MyIOUART_RX_P->IC |= (1<<MyIOUART_RX_P_INDEX); //clear flag
    										MyIOUART_RX_P->IE |= (1<<MyIOUART_RX_P_INDEX); //enable interrupt
    										//update len
    										l_RxDataLen = l_Rxbuffer[6];
                        //
    									  //reset timer	
    									  LPC_TMR32B1->TCR = 2;//[0-stop counter  1-start  2-reset]
    									  LPC_TMR32B1->IR = 1;
    
    								}
    						}
    			  }
        }
    		//--------------------------------
        LPC_GPIO0->DATA |= (1 << 3);//LED
    		//	
    		#if ENABLE_ECHO
        if(rx_interrupt_flag)
        {
    			rx_interrupt_flag = 0;//
    			recv_interrupt();//此函數必須立即返回!(用于回显测试)   
        }
    	  #endif
    }
    
    /*
    */
    
    /*USE EXAMPLE:
    */
    
    


    V1.6:单定时器方案

    1、DrvIOUART.h+DrvIOUART.c+DrvIOUART1.h+DrvIOUART1.c;蓝色文件为库文件,绿色文件为实例化参考

    2、资源占用:1个输入中断+1个定时器(针对实时要求不高的场合)

          文件详细见下载,末尾。

    使用小技巧:

    软件中,对.h文件的第一行添加"//<<< Use Configuration Wizard in Context Menu >>>",可使用其自带的配置功能,方便参数灵活设置。

    附录:

    1、IOUART模拟串口调试记录

      2016/10/20

    1、波特率可调节:支持收发波特率1200->57600

    [注: r字符进行回显测试,9600才能稳定不出错]

      

    19200(停止位为1)时:(单按时回显正常,按住不放回显会出错)

    停止位为2时,情况一样。

    结论:ZLG的模拟串口可以支持到57600,但连续接收数据过快时,baud>9600易出错。

    2、两路模拟串口实现

    两路模拟串口使用注意事项:

    1、两个模拟串口分布在不同PORT LINE,即一个用PORT2,一个用PORT3,不能用同一个PORT

    2、各自使用自己的定时器。

    3、每一个函数都要能立即退出,不要使其出现卡死现象。将每个函数想象成在一进就出、各不干扰、独立运行的状态执行。

    4、发送过程中产生接收,则以接收的优先级为高。

       增加发送自动退让,发送过程随时可能被接收中断,这样会导致发送的数据出现错误但接收的数据都是正常的。BUG.......................

       周立功串口写的很好在只使用一个定时器的情况下,做到了无一错发,无一漏收,可连续收发,波特率稳定可调,这才是正真的高手!!!

       增加接收数据计数,发送数据计数!

       增加当接收过程终止发送时拉高TX引脚操作!

       用串口调试助手测线序数据连续发送且能正常回显的最小时间,目前是300ms

       测试串:12 34 56 78 90 1A 3E 5B 12 34 56 78 90 1A 3E 5B

      

      

    5、对于连续接收情况的处理

       根据精确的停止位的后一位电平高低判断是否为连续接收的情况

       使用停止位判断,只能选择一位(k=0)或两位停止位(K=1

       没有校验位

       要求连续收发10个字节以上,不行的话调节BAUD系数

    6、一旦错过了起始位是否会一直出错!

    myiouart:

    特点

    1、支持一个定时器多通道引脚分时复用,通过channel选择。

         配置一个串口支持多个引脚发送,或接收通过channel变量选择哪一对引脚通道。

    3、测试模拟串口性能方法:

    使用回显测试:

    在secureCRT中: 按住两个按键不放看是否能正常显示,或同时按住多个看是否有乱码现象。当同时按住两个字符按键不放时,正常程序每次返回两个按下的字符,此时串口工作在连发状态下。

    在串口调试助手中:连续发送多个字节看返回值是否正确。

    4、Myiouart_Lpc11c14_V1程序DEBUG记录:

    V1.0 -- 只支持发送,接收波特率一高就有问题,4800接收

    V1.1 -- 修改了收发(只是单字节收发),跟换了32位定时器1,并将驱动单独列在一个文件中。

    V1.2 -- 增加了BUFFER功能

    V1.3 -- 增加了连续收发,但发送会被接收终止,导致发送的数据错误

    V1.4 --

    V1.5 -- 改为双定器模拟串口

    V1.6 -- 单定时器串口升级至V1.6使用了结构体操作方式

    参考:

    IO 模拟 UART 实现-ZLG

    链接:https://pan.baidu.com/s/1OgQshNoEe5oI0_g5cQPXHg 密码:0svc

    下载:

    V1.5

    链接:https://pan.baidu.com/s/11pwEpICOpuX6S5OYy6xUtg 密码:f5l9

    V1.6

    链接:https://pan.baidu.com/s/1UimbCwUY3uINvajBQ5d8HQ 密码:m044

  • 相关阅读:
    siteserver学习笔记
    移动端开发适配的2中方案
    移动端中适配问题
    2倍图3倍图怎么用
    常用的网站收藏
    关于用h5实现移动端的知识梳理
    悬浮广告代码
    vue中添加echarts
    VUE中给template组件加背景
    纯CSS控制背景图片100%自适应填充布局
  • 原文地址:https://www.cnblogs.com/time93/p/9347563.html
Copyright © 2020-2023  润新知