• 注册 / 登录
  • 切换到窄版
  • 查看: 1899|回复: 0

    STM32用IO模拟实现软件串口

    [复制链接]

    665

    主题

    679

    帖子

    6481

    积分

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    6481
    发表于 2022-9-5 21:20:41 | 显示全部楼层 |阅读模式

    路线栈欢迎您!

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    前言
    最近项目中STM32的串口资源紧张,于是使用IO口进行模拟串口,现进行整理记录。

    1. 实现思路
    IO口模拟串口的思路也比较简单,一切按照串口协议进行操作即可。
    对于发送,计算好不同波特率对应的延时时间进行数据发送。
    对于接收,稍微复杂。通过外部中断检测接收管脚的下降沿,检测到起始信号后开启定时器,定时器按照波特率设定好时间,每隔一段时间进入定时器中断接收数据,完成一个字节后关闭定时器。

    2. 测试Demo说明
    TXD  PC13
    RXD  PB14
    波特率:9600 ,1-8-N

    3. Demo功能
    接收11个数据,然后把接收到的数据发送出去。

    4. 程序实现
    1. #define OI_TXD  PCout(13)
    2. #define OI_RXD  PBin(14)

    3. #define BuadRate_9600   100

    4. u8 len = 0; //接收计数
    5. u8 USART_buf[11];  //接收缓冲区

    6. enum{
    7.     COM_START_BIT,
    8.     COM_D0_BIT,
    9.     COM_D1_BIT,
    10.     COM_D2_BIT,
    11.     COM_D3_BIT,
    12.     COM_D4_BIT,
    13.     COM_D5_BIT,
    14.     COM_D6_BIT,
    15.     COM_D7_BIT,
    16.     COM_STOP_BIT,
    17. };

    18. u8 recvStat = COM_STOP_BIT;
    19. u8 recvData = 0;

    20. void IO_TXD(u8 Data)
    21. {
    22.     u8 i = 0;
    23.     OI_TXD = 0;  
    24.     delay_us(BuadRate_9600);
    25.     for(i = 0; i < 8; i++)
    26.     {
    27.         if(Data&0x01)
    28.             OI_TXD = 1;  
    29.         else
    30.             OI_TXD = 0;     
    31.         
    32.         delay_us(BuadRate_9600);
    33.         Data = Data>>1;
    34.     }
    35.     OI_TXD = 1;
    36.     delay_us(BuadRate_9600);
    37. }
    38.    
    39. void USART_Send(u8 *buf, u8 len)
    40. {
    41.     u8 t;
    42.     for(t = 0; t < len; t++)
    43.     {
    44.         IO_TXD(buf[t]);
    45.     }
    46. }
    47.    
    48. void IOConfig(void)
    49. {
    50.     GPIO_InitTypeDef  GPIO_InitStructure;
    51.     NVIC_InitTypeDef NVIC_InitStructure;
    52.     EXTI_InitTypeDef EXTI_InitStruct;
    53.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE);     //使能PB,PC端口时钟
    54.      
    55.      //SoftWare Serial TXD
    56.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;      
    57.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       //推挽输出
    58.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      //IO口速度为50MHz   
    59.   GPIO_Init(GPIOC, &GPIO_InitStructure);                    
    60.   GPIO_SetBits(GPIOC,GPIO_Pin_13);                     
    61.      
    62.      
    63.     //SoftWare Serial RXD
    64.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
    65.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    66.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     
    67.     GPIO_Init(GPIOB, &GPIO_InitStructure);   

    68.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
    69.     EXTI_InitStruct.EXTI_Line = EXTI_Line14;
    70.     EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
    71.     EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling; //下降沿触发中断
    72.     EXTI_InitStruct.EXTI_LineCmd=ENABLE;
    73.     EXTI_Init(&EXTI_InitStruct);


    74.     NVIC_InitStructure.NVIC_IRQChannel= EXTI15_10_IRQn ;
    75.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
    76.     NVIC_InitStructure.NVIC_IRQChannelSubPriority =2;  
    77.     NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;  
    78.     NVIC_Init(&NVIC_InitStructure);  
    79.    
    80. }

    81. void TIM4_Int_Init(u16 arr,u16 psc)
    82. {
    83.   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    84.     NVIC_InitTypeDef NVIC_InitStructure;

    85.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能
    86.    
    87.     //定时器TIM4初始化
    88.     TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值   
    89.     TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
    90.     TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
    91.     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
    92.     TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
    93.     TIM_ClearITPendingBit(TIM4, TIM_FLAG_Update);
    94.     TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

    95.     //中断优先级NVIC设置
    96.     NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  //TIM4中断
    97.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级1级
    98.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //从优先级1级
    99.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
    100.     NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器            
    101. }


    102. int main(void)
    103. {      
    104.      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
    105.      delay_init();
    106.      IOConfig();
    107.   TIM4_Int_Init(107, 71);    //1M计数频率
    108.      
    109.   while(1)
    110.     {
    111.         if(len > 10)
    112.         {
    113.             len = 0;
    114.             USART_Send(USART_buf,11);
    115.         }
    116.     }
    117. }

    118. void EXTI15_10_IRQHandler(void)
    119. {
    120.     if(EXTI_GetFlagStatus(EXTI_Line14) != RESET)
    121.     {
    122.         if(OI_RXD == 0)
    123.         {
    124.             if(recvStat == COM_STOP_BIT)
    125.             {
    126.                 recvStat = COM_START_BIT;
    127.                 TIM_Cmd(TIM4, ENABLE);
    128.             }
    129.         }
    130.         EXTI_ClearITPendingBit(EXTI_Line14);
    131.     }
    132. }

    133. void TIM4_IRQHandler(void)
    134. {  
    135.     if(TIM_GetFlagStatus(TIM4, TIM_FLAG_Update) != RESET)
    136.     {
    137.         TIM_ClearITPendingBit(TIM4, TIM_FLAG_Update);   
    138.          recvStat++;
    139.         if(recvStat == COM_STOP_BIT)
    140.         {
    141.             TIM_Cmd(TIM4, DISABLE);
    142.             USART_buf[len++] = recvData;   
    143.             return;
    144.         }
    145.         if(OI_RXD)
    146.         {
    147.             recvData |= (1 << (recvStat - 1));
    148.         }else{
    149.             recvData &= ~(1 << (recvStat - 1));
    150.         }   
    151.   }     
    152. }
    复制代码

    5. Demo下载

    STM32 IO模拟实现软件串口.zip

    317.21 KB, 下载次数: 1

    作者:TonyCode

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|路丝栈 ( 粤ICP备2021053448号 )

    GMT+8, 2024-9-19 09:31 , Processed in 0.045041 second(s), 22 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表