| 
 | 
 
路线栈欢迎您!
您需要 登录 才可以下载或查看,没有帐号?立即注册 
 
 
 
x
 
前言 
最近项目中STM32的串口资源紧张,于是使用IO口进行模拟串口,现进行整理记录。 
 
1. 实现思路 
IO口模拟串口的思路也比较简单,一切按照串口协议进行操作即可。 
对于发送,计算好不同波特率对应的延时时间进行数据发送。 
对于接收,稍微复杂。通过外部中断检测接收管脚的下降沿,检测到起始信号后开启定时器,定时器按照波特率设定好时间,每隔一段时间进入定时器中断接收数据,完成一个字节后关闭定时器。 
 
2. 测试Demo说明 
TXD  PC13 
RXD  PB14 
波特率:9600 ,1-8-N 
 
3. Demo功能 
接收11个数据,然后把接收到的数据发送出去。 
 
4. 程序实现 
- #define OI_TXD  PCout(13)
 
 - #define OI_RXD  PBin(14)
 
  
- #define BuadRate_9600   100
 
  
- u8 len = 0; //接收计数
 
 - u8 USART_buf[11];  //接收缓冲区
 
  
- 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,
 
 - };
 
  
- u8 recvStat = COM_STOP_BIT;
 
 - u8 recvData = 0;
 
  
- void IO_TXD(u8 Data)
 
 - {
 
 -     u8 i = 0;
 
 -     OI_TXD = 0;  
 
 -     delay_us(BuadRate_9600);
 
 -     for(i = 0; i < 8; i++)
 
 -     {
 
 -         if(Data&0x01)
 
 -             OI_TXD = 1;  
 
 -         else
 
 -             OI_TXD = 0;     
 
 -         
 
 -         delay_us(BuadRate_9600);
 
 -         Data = Data>>1;
 
 -     }
 
 -     OI_TXD = 1;
 
 -     delay_us(BuadRate_9600);
 
 - }
 
 -     
 
 - void USART_Send(u8 *buf, u8 len)
 
 - {
 
 -     u8 t;
 
 -     for(t = 0; t < len; t++)
 
 -     {
 
 -         IO_TXD(buf[t]);
 
 -     }
 
 - }
 
 -     
 
 -  void IOConfig(void)
 
 -  {
 
 -     GPIO_InitTypeDef  GPIO_InitStructure;
 
 -     NVIC_InitTypeDef NVIC_InitStructure;
 
 -     EXTI_InitTypeDef EXTI_InitStruct;
 
 -   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE);     //使能PB,PC端口时钟 
 
 -      
 
 -      //SoftWare Serial TXD
 
 -     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;      
 
 -   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       //推挽输出
 
 -   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      //IO口速度为50MHz   
 
 -   GPIO_Init(GPIOC, &GPIO_InitStructure);                    
 
 -   GPIO_SetBits(GPIOC,GPIO_Pin_13);                      
 
 -      
 
 -      
 
 -     //SoftWare Serial RXD
 
 -     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
 
 -   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
 
 -   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     
 
 -     GPIO_Init(GPIOB, &GPIO_InitStructure);   
 
  
-     GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
 
 -     EXTI_InitStruct.EXTI_Line = EXTI_Line14;
 
 -     EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
 
 -     EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling; //下降沿触发中断
 
 -     EXTI_InitStruct.EXTI_LineCmd=ENABLE;
 
 -     EXTI_Init(&EXTI_InitStruct);
 
  
 
-     NVIC_InitStructure.NVIC_IRQChannel= EXTI15_10_IRQn ; 
 
 -     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2; 
 
 -     NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;  
 
 -     NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;  
 
 -     NVIC_Init(&NVIC_InitStructure);  
 
 -     
 
 - }
 
 -  
 
 - void TIM4_Int_Init(u16 arr,u16 psc)
 
 - {
 
 -   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
 
 -     NVIC_InitTypeDef NVIC_InitStructure;
 
  
-     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能
 
 -     
 
 -     //定时器TIM4初始化
 
 -     TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值   
 
 -     TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
 
 -     TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
 
 -     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
 
 -     TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
 
 -     TIM_ClearITPendingBit(TIM4, TIM_FLAG_Update);
 
 -     TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
 
  
-     //中断优先级NVIC设置
 
 -     NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  //TIM4中断
 
 -     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级1级
 
 -     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //从优先级1级
 
 -     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
 
 -     NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器            
 
 - }
 
 -  
 
 -  
 
 -  int main(void)
 
 -  {      
 
 -      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
 
 -      delay_init();
 
 -      IOConfig();
 
 -   TIM4_Int_Init(107, 71);    //1M计数频率
 
 -      
 
 -   while(1)
 
 -     {
 
 -         if(len > 10)
 
 -         {
 
 -             len = 0;
 
 -             USART_Send(USART_buf,11);
 
 -         }
 
 -     }
 
 - }
 
  
- void EXTI15_10_IRQHandler(void)
 
 - {
 
 -     if(EXTI_GetFlagStatus(EXTI_Line14) != RESET)
 
 -     {
 
 -         if(OI_RXD == 0) 
 
 -         {
 
 -             if(recvStat == COM_STOP_BIT)
 
 -             {
 
 -                 recvStat = COM_START_BIT;
 
 -                 TIM_Cmd(TIM4, ENABLE);
 
 -             }
 
 -         }
 
 -         EXTI_ClearITPendingBit(EXTI_Line14);
 
 -     }
 
 - }
 
  
- void TIM4_IRQHandler(void)
 
 - {  
 
 -     if(TIM_GetFlagStatus(TIM4, TIM_FLAG_Update) != RESET)
 
 -     {
 
 -         TIM_ClearITPendingBit(TIM4, TIM_FLAG_Update);   
 
 -          recvStat++;
 
 -         if(recvStat == COM_STOP_BIT)
 
 -         {
 
 -             TIM_Cmd(TIM4, DISABLE);
 
 -             USART_buf[len++] = recvData;    
 
 -             return;
 
 -         }
 
 -         if(OI_RXD)
 
 -         {
 
 -             recvData |= (1 << (recvStat - 1));
 
 -         }else{
 
 -             recvData &= ~(1 << (recvStat - 1));
 
 -         }   
 
 -   }     
 
 - }
 
  复制代码 
5. Demo下载 
 
 |   
 
 
 
 |