c/c++语言开发共享stm32 普通IO口模拟串口通信

普通IO口模拟串口通信 串口通信协议 串口通信协议 串口传输 默认 波特率9600 1起始位 1停止位 其他0 数据位是8位(注意图上的给错了)。 用于知识梳理积累,写的比较随意 有问题可以发邮箱联系我 udpmeettcp@163.com …


普通io口模拟串口通信

  • 串口通信协议  

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 char temp_bin = 0;//用于记录二进制值  17         unsigned long long current_time = sys_micros();//记下此刻时间  18         unsigned short interval_time = current_time - m_rx_previous_time;//计算一个状态持续的时长   19         m_rx_previous_time = current_time;//为下次计算时长做准备  20           21         //当前未开始一个字节的接收且此时为下降沿  22         if(rebit == 10)//10 当数据不合法时或者结束传输时 rebit值设为10  23         {  24             if(!pcin(8))//下降沿  25             {  26                 rebit = 0;//记下开始接收  27                 m_rx_begin_f = 1;  28                 debug_led(1,led_toggle);  29             }  30         }  31         //已经开始接收  32         else  33         {  34             //上一状态为起始位  35             if(!rebit)//起始位0  36             {  37                 //计算二进制数据的个数  38                 skip_index = (interval_time/50)-1;  39   40                 //个数合法  41                 if(skip_index <= 9)  42                 {  43                     //根据状态保持时间更新接收值                 44                     for(i = 0;i < skip_index;i++)  45                     {  46                         recev[i] = 0;  47                       48                     }  49   50                     //更新接收二进制位的下标  51                     rebit = skip_index;  52                       53                 }  54                 //不合法-重新接收  55                 else   56                 {  57                     rebit = 10;  58                     m_rx_begin_f = 0;  59                       60                       61                 }              62             }  63             //上一状态为数据位  64             else  65             {  66                 //计算二进制数据的个数  67                 skip_index = interval_time/50;  68   69                 //数据不合法-重新接收  70                 if((skip_index+rebit) > 9)//所处位置+数据个数 判断数据是否超10 合法判断  71                 {  72                     //printf("skip_index %d   rebit=%d rn",skip_index,rebit);  73                     rebit = 10;  74                     m_rx_begin_f = 0;  75                     debug_led(3,led_toggle);  76                 }  77                 //数据合法  78                 else  79                 {  80                     //当前为高电平  81                     if(pcin(8))  82                     {  83                      temp_bin = 1;//0  84                     }  85                     else  86                     {  87                      temp_bin = 0;//1 change  88                     }  89                     debug_led(2,led_toggle);  90                     for(i = 0;i < skip_index ;i++)//根据几个数据 给予相应的位  91                     {  92                         recev[rebit+i+1] = temp_bin;//change +1  93                         rebit++;  94               95                     }  96                 }  97                   98                 //数据已接收至结束位  99                 if(rebit >= 8 )//=8>? 100                 { 101                     if(irrec_rx_cnt < 64) 102                     { 103                         irrec_rx_buf[irrec_rx_cnt++]     = (recev[7] << 7) |(recev[6] << 6)| (recev[5] << 5)| (recev[4] << 4)| (recev[3] << 3) |(recev[2] << 2) |(recev[1] << 1) |recev[0]; 104                          105                     } 106                     rebit = 10; 107                     m_rx_begin_f = 0; 108  109                      110                 } 111                  112             } 113         } 114          115  116         #endif 117         exti_clearitpendingbit(exti_line8);//清除中断挂起标志位 118  119     } 120  121 }

 

用于知识梳理积累,写的比较随意  

有问题可以发邮箱联系我   udpmeettcp@163.com 

 

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/c-cdevelopment/602458.html

(0)
上一篇 2021年5月11日
下一篇 2021年5月11日

精彩推荐