当前位置:   article > 正文

STM32学习笔记 IO口模拟串口 (接收采用定时器方式)_stm32 gpio模拟串口

stm32 gpio模拟串口

一、概述

        硬件:基于STM32F407VET6编写

        软件:使用两个GPIO口,一个用作串口发送TX,一个用作串口接收RX,采用的是定时器模拟                     时序。

二、串口简介

        要模拟串口,首先肯定是需要了解串口的协议,根据协议来编写程序。

        

        UART的通信方式是由1个起始位,8个数据位,包含一个奇偶校验位,和结束位构成 。在本次的设计中默认为波特率为9600,停止位为1位,8位数据位,无奇偶校验位。

        先介绍起始位,从高电平跳变为低电平,表示通信开始。再来简单介绍下波特率,单位时间内传送码元符号的个数,波特率9600,也就是1s内传送9600个bit,一个bit所需要的时间为 1000000us / 9600 = 104.166 us,也就是104us。

三、程序实现

3.1 头文件参数定义

  1. #ifndef _S_UART_H_
  2. #define _S_UART_H_
  3. #include "sys.h"
  4. #include "delay.h"
  5. //定义通信波特率
  6. #define BaudRate_9600 104 //1000000us/9600=104.1666 发送1个位所需要的时间
  7. //GPIO定义
  8. #define S_Uart_Tx PCout(3) //模拟串口TX端
  9. #define S_Uart_Rx PCin(4) //模拟串口RX端
  10. typedef enum{
  11. State_State = 0, //起始状态
  12. State_transfer, //传输状态
  13. State_Stop, //停止状态
  14. }UartState;
  15. #define SUartLength 200 //模拟串口缓冲区长度
  16. extern u8 SUartCnt; //模拟串口缓冲区位置
  17. extern u8 SUartBuff[SUartLength]; //模拟串口缓冲区
  18. void S_Uart_GPIO_Init(void);
  19. void S_Uart_Send_Buff(u8 *buff,u8 length);
  20. u8 S_Uart_Rx_Handler(u8 *buf,u8 *length);
  21. #endif

3.2 GPIO的初始化        

  1. //模拟串口GPIO初始化
  2. void S_Uart_GPIO_Init(void)
  3. {
  4. GPIO_InitTypeDef GPIO_InitStruct;
  5. EXTI_InitTypeDef EXTI_InitStruct;
  6. NVIC_InitTypeDef NVIC_InitStruct;
  7. //开时钟
  8. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
  9. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
  10. GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3; //TX GPIOC3
  11. GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; //推挽输出
  12. GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
  13. GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //上拉
  14. GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
  15. GPIO_Init(GPIOC, &GPIO_InitStruct);
  16. S_Uart_Tx = 1;
  17. GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4; //RX GPIOC4
  18. GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; //上拉输入
  19. GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
  20. GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
  21. GPIO_Init(GPIOC,&GPIO_InitStruct);
  22. }

3.3 模拟串口发送        

  1. //模拟串口发送一个字节
  2. void S_Uart_One_Tx(u8 Data)
  3. {
  4. u8 i;
  5. S_Uart_Tx=0; //起始位
  6. delay_us(BaudRate_9600);
  7. for(i=0; i<8; i++)
  8. {
  9. if(Data & 0x01) //串口协议 先发LSB
  10. S_Uart_Tx = 1;
  11. else
  12. S_Uart_Tx = 0;
  13. delay_us(BaudRate_9600);
  14. Data >>= 1;
  15. }
  16. S_Uart_Tx = 1;
  17. delay_us(BaudRate_9600);
  18. }
  19. //模拟串口发送数据
  20. void S_Uart_Send_Buff(u8 *buff,u8 length)
  21. {
  22. for(u8 i=0; i<length; i++)
  23. {
  24. S_Uart_One_Tx(buff[i]);
  25. }
  26. }

  3.4 模拟串口接收

        需要开启一个定时器中断,对模拟串口的电平进行监视,废话不多说,直接上代码。

  1. void Time4_Init(u16 arr,u16 psc)
  2. {
  3. TIM_TimeBaseInitTypeDef Tim4_TimeBaseStruct;
  4. NVIC_InitTypeDef NVIC_InitStruct;
  5. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
  6. Tim4_TimeBaseStruct.TIM_Period = arr; //重载值
  7. Tim4_TimeBaseStruct.TIM_Prescaler = psc; //预分频值
  8. Tim4_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
  9. Tim4_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
  10. TIM_TimeBaseInit(TIM4,&Tim4_TimeBaseStruct);
  11. TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
  12. TIM_Cmd(TIM4,ENABLE);
  13. NVIC_InitStruct.NVIC_IRQChannel = TIM4_IRQn;
  14. NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  15. NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01;
  16. NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
  17. NVIC_Init(&NVIC_InitStruct);
  18. }
  19. void TIM4_IRQHandler(void)
  20. {
  21. static u8 value=0;
  22. static UartState M_State = State_State;
  23. static u8 bit_cnt;
  24. if(TIM_GetFlagStatus(TIM4,TIM_FLAG_Update) != RESET)
  25. {
  26. TIM_ClearITPendingBit(TIM4,TIM_FLAG_Update);
  27. if(S_Uart_Rx==0 && M_State == State_State) //起始位 下降沿
  28. {
  29. M_State = State_transfer; //接收到起始位,状态为传输中
  30. bit_cnt=0;
  31. }
  32. else if(M_State == State_transfer)
  33. {
  34. bit_cnt++;
  35. if(S_Uart_Rx)
  36. {
  37. value |= (1<<(bit_cnt-1));
  38. }
  39. else
  40. {
  41. value &= ~(1<<(bit_cnt-1));
  42. }
  43. if(bit_cnt >= 8)
  44. M_State = State_Stop;
  45. }
  46. else if(S_Uart_Rx && M_State==State_Stop)
  47. {
  48. bit_cnt=0;
  49. if(SUartCnt < SUartLength)
  50. SUartBuff[SUartCnt++] = value; //存入缓冲区
  51. else
  52. SUartCnt = 0;
  53. M_State = State_State; //状态回到起始状态,坐等下一帧数据
  54. }
  55. }
  56. }
  57. //接收串口数据处理
  58. u8 S_Uart_Rx_Handler(u8 *buf,u8 *length)
  59. {
  60. *length = 0;
  61. if(SUartCnt > 0) //模拟串口缓冲区不为空
  62. {
  63. *length = SUartCnt;
  64. memcpy(buf,SUartBuff,*length); //
  65. SUartCnt = 0;
  66. }
  67. return *length;
  68. }

3.5 主函数调用

  1. int main(void)
  2. {
  3. u16 i;
  4. u8 len;
  5. //u8 buff[5]={0,1,2,3,4};
  6. u8 buff[200];
  7. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
  8. delay_init(168); //延时初始化
  9. LED_Init(); //初始化与LED连接的硬件接口
  10. S_Uart_GPIO_Init(); //模拟串口
  11. Time4_Init(BaudRate_9600,84-1); //104us
  12. while(1)
  13. {
  14. if(S_Uart_Rx_Handler(buff,&len))
  15. {
  16. S_Uart_Send_Buff(buff,len); //将接收到的数据发送出去
  17. }
  18. if(++i %100 == 0)
  19. {
  20. i=0;
  21. LED0 = !LED0;
  22. //S_Uart_Send_Buff(buff,5);
  23. }
  24. delay_ms(10);
  25. }
  26. }

四、程序执行效果

单片机将模拟串口接收到的数据用模拟串口发送出去。 

 好了,内容到此结束了,制作不易,如果对大家有帮助麻烦点个赞,谢谢!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/302034
推荐阅读
相关标签
  

闽ICP备14008679号