普通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(){ EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //使能GPIOC时钟 //IR TX C9 使能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_SetBits(GPIOC, GPIO_Pin_9);// 引脚拉高 //IR RX C8
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource8); EXTI_InitStructure.EXTI_Line=EXTI_Line8;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=
EXTI_Trigger_Rising_Falling;
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStructure); NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure); }
 void IR_SendByte(u8 val)//发送bit位
{
u16 i; IRSEND=;//拉低 开始传输
SysTick_Delay_Us();//波特率根据延时在设置 19200波特率 for(i=;i<;i++)
{
if(val&0x1)
{
IRSEND=;
}
else
{
IRSEND=;
} val>>=;
SysTick_Delay_Us();
} IRSEND=;
SysTick_Delay_Us();
} void IR_SendStr(u8*st,u16 len){//在这填入16位数据即可
int i=;
while ((len--)!=)
{
IR_SendByte(st[i]);
i++;
} }
 u8 IRREC_RX_BUF[]={};    //接收缓冲,最大64个字节.
//接收到的数据长度
u8 IRREC_RX_CNT=; char rebit=stopbit;//记录接收一个字节的二进制位所处何种位置
u8 Recev[]={};//记录接收的一个字节的二进制流 static volatile unsigned long long m_rx_previous_time = ;//上一次进入中断时间
static volatile unsigned char m_rx_begin_f = ;//开始一个字节的接收标志 0-无数据开始接收 1-有数据开始接收
void EXTI9_5_IRQHandler(void){ if(EXTI_GetITStatus(EXTI_Line8)!=RESET)
{
unsigned char skip_index = ;
unsigned char i = ;
unsigned char temp_bin = ;//用于记录二进制值
unsigned long long current_time = sys_micros();//记下此刻时间
unsigned short interval_time = current_time - m_rx_previous_time;//计算一个状态持续的时长
m_rx_previous_time = current_time;//为下次计算时长做准备 //当前未开始一个字节的接收且此时为下降沿
if(rebit == )//10 当数据不合法时或者结束传输时 rebit值设为10
{
if(!PCin())//下降沿
{
rebit = ;//记下开始接收
m_rx_begin_f = ;
debug_led(,LED_TOGGLE);
}
}
//已经开始接收
else
{
//上一状态为起始位
if(!rebit)//起始位0
{
//计算二进制数据的个数
skip_index = (interval_time/)-; //个数合法
if(skip_index <= )
{
//根据状态保持时间更新接收值
for(i = ;i < skip_index;i++)
{
Recev[i] = ; } //更新接收二进制位的下标
rebit = skip_index; }
//不合法-重新接收
else
{
rebit = ;
m_rx_begin_f = ; }
}
//上一状态为数据位
else
{
//计算二进制数据的个数
skip_index = interval_time/; //数据不合法-重新接收
if((skip_index+rebit) > )//所处位置+数据个数 判断数据是否超10 合法判断
{
//printf("skip_index %d rebit=%d \r\n",skip_index,rebit);
rebit = ;
m_rx_begin_f = ;
debug_led(,LED_TOGGLE);
}
//数据合法
else
{
//当前为高电平
if(PCin())
{
temp_bin = ;//
}
else
{
temp_bin = ;//1 change
}
debug_led(,LED_TOGGLE);
for(i = ;i < skip_index ;i++)//根据几个数据 给予相应的位
{
Recev[rebit+i+] = temp_bin;//change +1
rebit++; }
} //数据已接收至结束位
if(rebit >= )//=8>?
{
if(IRREC_RX_CNT < )
{
IRREC_RX_BUF[IRREC_RX_CNT++] = (Recev[] << ) |(Recev[] << )| (Recev[] << )| (Recev[] << )| (Recev[] << ) |(Recev[] << ) |(Recev[] << ) |Recev[]; }
rebit = ;
m_rx_begin_f = ; } }
} #endif
EXTI_ClearITPendingBit(EXTI_Line8);//清除中断挂起标志位 } }

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

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

stm32 普通IO口模拟串口通信的更多相关文章

  1. 51单片机GPIO口模拟串口通信

    51单片机GPIO口模拟串口通信 标签: bytetimer终端存储 2011-08-03 11:06 6387人阅读 评论(2) 收藏 举报 本文章已收录于:   分类: 深入C语言(20) 作者同 ...

  2. 【STM32】IIC的基本原理(实例:普通IO口模拟IIC时序读取24C02)(转载)

     版权声明:本文为博主原创文章,允许转载,但希望标注转载来源. https://blog.csdn.net/qq_38410730/article/details/80312357 IIC的基本介绍 ...

  3. STM32的IO口的8种配置

    STM32的IO口的8种配置 1 STM32的输入输出管脚有以下8种可能的配置:(4输入+2输出+2复用输出) ① 浮空输入_IN_FLOATING ② 带上拉输入_IPU ③ 带下拉输入_IPD ④ ...

  4. 转载电子发烧友网---STM32的IO口灌入电流和输出驱动电流

    刚开始学习一款单片机的时候一般都是从操作IO口开始的,所以我也一样,先是弄个流水灯. 刚开始我对STM32的认识不够,以为是跟51单片机类似,可以直接操作端口,可是LED灯却没反应,于是乎,仔细查看资 ...

  5. STM32中IO口的8中工作模式

    该文摘自:http://blog.csdn.net/kevinhg/article/details/17490273 一.推挽输出:可以输出高.低电平,连接数字器件:推挽结构一般是指两个三极管分别受两 ...

  6. MSP430的IO口模拟I2C总线对AT24C25进行读写程序

    功能: 实现MSP430口线模拟I2C总线协议与24C04通信.                                           ** 描述: 主系统工作时钟为12MHz,I2C工 ...

  7. System.IO.Ports.SerialPort串口通信接收完整数据

    C#中使用System.IO.Ports.SerialPort进行串口通信网上资料也很多,但都没有提及一些细节: 比如 串口有时候并不会一次性把你想要的数据全部传输给你,可能会分为1次,2次,3次分别 ...

  8. STM32的IO口是如何配置为某个外设使用的 ---?

    @2019-03-01 [猜想] 使用片内外设功能: 首先将对应 IO 口配置为复用输出 其次是 IO 口对应的多个功能外设,哪个外设使能即将外设与 IO 口相连 [疑问] 若多个外设都使能,那么到底 ...

  9. 玩转X-CTR100 l STM32 l STM32F4 l 蓝牙串口通信

    我造轮子,你造车,创客一起造起来!更多塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ]      蓝牙串口通信模块,X-CTR100控制 ...

随机推荐

  1. 浅谈Vue.js2.0核心思想

    Vue.js是一个提供MVVM数据双向绑定的库,专注于UI层面,核心思想是:数据驱动.组件系统. 数据驱动: Vue.js数据观测原理在技术实现上,利用的是ES5Object.defineProper ...

  2. 攻防世界 高手进阶区 web cat

    php cURL CURLOPT_SAFE_UPLOAD django DEBUG mode Django使用的是gbk编码,超过%F7的编码不在gbk中有意义 当 CURLOPT_SAFE_UPLO ...

  3. HTML实现百度分享插件分享网页

    一.HTML代码如下: <div class="bdsharebuttonbox"> <a href="#" class="bds_ ...

  4. nodeJs 报maximum call stack size exceeded js

    先看错误 查了下资料说是什么js堆栈异常,是递归造成的啥的,但我程序里没用到啥递归,整了老半天将collection-repeat换成ng-repeat然后就好啦,具体原因待探讨.

  5. 04——Solr学习之项目中使用solr

    借鉴博客:https://blog.csdn.net/kisscatforever/article/details/76744768 完全可以跟着他这个来,清晰明了. 一.来说说怎么使用solr这玩意 ...

  6. 利用pandas映射替换两个字典中的映射值

    在公司处理报表,中英文映射表与数值表替换 import pandas as pd data = { "a":"值一", "b":" ...

  7. Nginx下HTML页面POST请求静态JSON数据返回405状态

    在浏览器访问HTML页面,发现一些静态JSON数据没有显示,F12查看,如下图所示: 可以看到请求方式为POST 将请求链接复制在浏览器地址栏访问,可以正常请求到数据 F12查看,可以看到请求方式为G ...

  8. win10 任务栏上的工具栏,重启消失的解决方法

    首先谈下 <任务栏的工具栏> 对于很多人来言,还是有可取性的 任务栏的工具栏对编程者的作用 一般来说,我们会经常查看某些API文档,虽然现在是联网也很方便,但如果都下载下来,整理到一个文件 ...

  9. C#中的函数(三)参数传递及返回值

    接前面二篇,继续开始新的研究 前面忘了说什么是主调函数与被调函数 主调函数:执行调用其它函数语句所在的函数 被调函数:被其它函数所调用的函数 简单说就是一个是发起调用者,另一个是被调用者 写个小例子说 ...

  10. 关于selectpicker的多选问题

    刚开始拿到这个需要求的时候,我时很没有头绪的,再前期做的时候是将这个多选的作为一个数组,传入到后端,然后再插入数据库中,然后根据关系表查询,因为但是考虑显示的问题,不知道怎么将多选的数据显示出来,我就 ...