TOP

stm32 普通IO口模拟串口通信(一)
2019-08-04 00:07:07 】 浏览:91
Tags:stm32 普通 模拟 串口 通信

普通IO口模拟串口通信

  • 串口通信协议  

  1. 串口传输 默认 波特率9600 1起始位 1停止位 其他0 数据位是8位(注意图上的给错了)。

  2. 传输时,从起始位开始,从一个数据的低位(LSB)开始发送,如图从左向右的顺序,对电平拉高或拉低,最后停止位时拉高。
  3. 波特率大小,改变延时时间即可。例如9600 波特率    根据公式 : 1/9600=0.000104s(大致) 也就是说每发送1bit延时104us (下面我用9600波特率来说,代码用的是19200)
  4. 串口发送       将电平拉低 延时104us(视为 起始位 0   传输数据正式开始)  其中数据我发送的是16进制数据(8bit  一字节  例如10001000)  将想要发的数据按照二进制的‘0’‘1’高低电平的方式,每发送1bit 延时104us   直到发送完到终止位 将电平拉高视为一包数据传输结束。(根据需求更改即可)
  5. 串口接收    (稍微麻烦一些) 两种方法:第一种可以用定时中断,每隔104us开启一次定时中断,中断函数内进行高低电平判断,将这些bit存储最后转换成需要的数据。第二种,用外部中断处理函数,外部中断设置同时开启上升沿下降沿,思路:根据上升下降的电平跳变分析。比如说,触发外部中断后检测电平高低,记录一下当前时间,然后再进入外部中断后 计算出总共几个bit   (两个沿跳变之间的时间 =现在记录的时间 — 之前记录的时间        bit=这个时间/104us)  ,知道这个就可以转换数据了。
  6. 定时中断逻辑相对外部中断而言简单好写,但是数据多的时候准确率下降很多,容易丢数据(因为定时中断毕竟用计时开启中断,不可能时间准确每104us开启一次,数据一多时间误差大,自然丢包。可以尝试每发一串数据,重新计时校准一次)。外部中断较为准确,检测的高低电平跳变较为明显唯一,一个跳变就是一个数据,只是分析情况比较多。
  //IO模拟串口初始化
1
void IRrec_Init(){ 2 3 4 EXTI_InitTypeDef EXTI_InitStructure; 5 NVIC_InitTypeDef NVIC_InitStructure; 6 GPIO_InitTypeDef GPIO_InitStructure; 7 8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //使能GPIOC时钟 9 10 11 //IR TX C9 使能 12 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; 13 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 14 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 15 GPIO_Init(GPIOC, &GPIO_InitStructure); 16 GPIO_SetBits(GPIOC, GPIO_Pin_9);// 引脚拉高 17 18 19 //IR RX C8 20 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); 21 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; 22 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 23 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 24 GPIO_Init(GPIOC, &GPIO_InitStructure); 25 GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource8); 26 27 EXTI_InitStructure.EXTI_Line=EXTI_Line8; 28 EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; 29 EXTI_InitStructure.EXTI_Trigger= 30 EXTI_Trigger_Rising_Falling; 31 EXTI_InitStructure.EXTI_LineCmd=ENABLE; 32 EXTI_Init(&EXTI_InitStructure); 33 34 NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn; 35 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2; 36 NVIC_InitStructure.NVIC_IRQChannelSubPriority=2; 37 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; 38 NVIC_Init(&NVIC_InitStructure); 39 40 }
 1 void IR_SendByte(u8 val)//发送bit位
 2 {
 3     u16 i;
 4     
 5     IRSEND=0;//拉低 开始传输
 6     SysTick_Delay_Us(53);//波特率根据延时在设置  19200波特率   
 7     
 8     for(i=0;i<8;i++)
 9     {
10         if(val&0x1)
11         {
12             IRSEND=1;
13         }
14         else
15         {
16             IRSEND=0;
17         }
18
19         val>>=1;
20         SysTick_Delay_Us(53);
21     }
22     
23     IRSEND=1;
24     SysTick_Delay_Us(53);
25 }
26 
27 
28 void IR_SendStr(u8*st,u16 len){//在这填入16位数据即可
29     int i=0;
30     while ((len--)!=0)
31     {  
32         IR_SendByte(st[i]);
33         i++;
34     }
35 
36 }
  1 u8 IRREC_RX_BUF[64]={0};    //接收缓冲,最大64个字节.
  2     //接收到的数据长度
  3     u8 IRREC_RX_CNT=0; 
  4 
  5 char rebit=stopbit;//记录接收一个字节的二进制位所处何种位置
  6 u8 Recev[8]={0};//记录接收的一个字节的二进制流
  7 
  8 static volatile unsigned long long m_rx_previous_time = 0;//上一次进入中断时间
  9 static volatile unsigned char m_rx_begin_f = 0;//开始一个字节的接收标志 0-无数据开始接收 1-有数据开始接收
 10 void EXTI9_5_IRQHandler(void){
 11 
 12     if(EXTI_GetITStatus(EXTI_Line8)!=RESET)
 13     {
 14         unsigned char skip_index = 0;
 15         unsigned char i = 0;
 16         unsigned c  
		
stm32 普通IO口模拟串口通信(一) https://www.cppentry.com/bencandy.php?fid=45&id=227858

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇回调函数的作用 下一篇fdsafdas