模拟串口实现方案

来源:互联网 发布:mac可以练vf 编辑:程序博客网 时间:2024/05/29 16:30

最近做了一个项目,由于需要6个串口,单片机串口串口资源不够用,就用stm32单片机模拟了几路串口,波特率9600.

1、首先,我们先了解串行通信数据格式


2、数据发送端

        实现方案:模拟串口的波特率为9600,故我们延时时间为104us,根据通信数据格式起始位为低电平,停止位为高电平。

/*

*********************************************************************************************************

*       函 数 名: SendOneByte

*       功能说明: 模拟串口发送一字节数据

*       形    参:无

*       返 回 值: 无

*********************************************************************************************************

*/

 

void SendOneByte(uint8_t datatoSend)

{

         uint8_ti, tmp;

 

         /*Start bit */

         TXD_low();

         delay_us(SendingDelay);

         for(i= 0; i < 8; i++)

         {

                   tmp  = (datatoSend >> i) & 0x01;

 

                   if(tmp== 0)

                   {

                            TXD_low();

                            delay_us(SendingDelay); //0            

                   }

                   else

                   {

                            TXD_high();

                            delay_us(SendingDelay); //1            

                   }       

         }       

         /*Stop bit */

         TXD_high();

         delay_us(SendingDelay);

}

3、数据接收端

         实现方案:串口接收数据实现比较复杂,

    1、IO口需配置成外部中断(下降沿触发)

    2、外部中断触发,开启定时中断TIM1

    3、TIM1函数处理:第一位检测到低电平,接收到起始位,后面8位为数据位,后再 检测到高电平,一个字节接收结束。

  第一步:配置外部中断和104us定时器

static void EXTI_Configuration(void)

{

       EXTI_InitTypeDef EXTI_InitStructure;

       NVIC_InitTypeDef NVIC_InitStructure;

 

                   /*Enable the AFIO Clock */

       RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

 

   GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource12);

 

   /* Configure Button EXTI line */

   EXTI_InitStructure.EXTI_Line = EXTI_Line12;

   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 

 

   EXTI_InitStructure.EXTI_LineCmd = ENABLE;

   EXTI_Init(&EXTI_InitStructure);

 

   /* Enable and set Button EXTI Interrupt to the lowest priority */

   NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;

   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;

   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;

   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

 

   NVIC_Init(&NVIC_InitStructure);

}

 

 

/*

*********************************************************************************************************

*       函 数 名: TIM1_Configuration

*       功能说明: 配置TIM1

*       形    参:无

*       返 回 值: 无

*********************************************************************************************************

*/

 

void TIM1_Configuration(void)

{

                   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

           NVIC_InitTypeDef NVIC_InitStructure;

 

          RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);

 

       /* Time base configuration */

       TIM_TimeBaseStructure.TIM_Period =SendingDelay -1;

       TIM_TimeBaseStructure.TIM_Prescaler = 72-1;

                   TIM_TimeBaseStructure.TIM_ClockDivision= 0;

       TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up;

 

       TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);

 

 

                   TIM_ClearITPendingBit(TIM1,TIM_FLAG_Update);

        

         /*开启TIM1的中断 */

   TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);    

       

 

   /* 选择TIM2的中断通道 */

   NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;     

   

         /*抢占式中断优先级设置为0 */

   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

   

         /*响应式中断优先级设置为0 */

   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

   

         /*使能中断 */

   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

   NVIC_Init(&NVIC_InitStructure);

}

 

第二步:外部中断触发:

 

void EXTI15_10_IRQHandler(void)

         if(EXTI_GetFlagStatus(EXTI_Line12)!= RESET)

         {

                   /*Disable the Selected IRQ Channels -------------------------------------*/

        

         EXTI->IMR &= ~1<<12;   //屏蔽外部中断

                   if(Rx1Flag== 0)

                   {

                                     Rx1Flag= 1;

                   }

                  

                TIM_Cmd(TIM1,DISABLE);               //开启TIM1

                   TIM_SetCounter(TIM1,0);

                   TIM_Cmd(TIM1,ENABLE);                //开启TIM1

         }

}

第三步:定时器处理,接收一个字节数据

void TIM1_UP_IRQHandler(void)

{

         staticuint8_t tmp;

         staticuint8_t i,j;    

         if(TIM_GetFlagStatus(TIM1,TIM_FLAG_Update) != RESET)

         {              

   if(Rx1Flag == 1)

                   {                       

                            Rx1Flag= 2;

                            i=0;

                   }              

                   elseif(Rx1Flag == 2)

                   {

                            tmp= GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12);       

                            if(tmp== 1)

                                     dataReceived[receivedNum]|= (1 << i);

     else dataReceived[receivedNum] &= ~(1 << i);                    

                     i++;

           }        

                   if(i>= 8)

                   {

                            Rx1Flag= 0;

                            i= 0;

                            receivedNum++;      

                 EXTI->IMR |= 1<<12;   //屏蔽外部中断

                            TIM_Cmd(TIM1,DISABLE);               //关闭TIM1

                   } 

                   TIM_ClearITPendingBit(TIM1,TIM_FLAG_Update);

         }

}

原创粉丝点击