- 串口调试advantage:借助强大的电脑来调试
- 点灯调试法
- 注释调试法
- 对照法
OLED_ShowChar(1,?1,?'A'); | 显示一个字符 | 指定起始行,指定起始列,显示字符 | |
OLED_ShowNum(2,?1,?12345,?5); | 显示十进制数字 | OLED_ShowSignedNum(2,?7,?-66,?2); | 显示有符号十进制数字 | OLED_ShowHexNum(3,?1,?0xAA55,?4); | 显示十六进制数字 | OLED_ShowBinNum(4,?1,?0xAA55,?16); | 显示二进制数字 | 最后一位是显示数字的长度 | |
4-1 OLED显示编程中的一些思想:
OLED的供电孔同时也会接到STM32的PB6、PB7引脚,只要不初始化这两个引脚,
不初始化的话——默认为浮空输入模式——引脚不会输出电平,无影响
方法2:也可不接PB6、PB7的两根跳线,直接给PB6 0 ,给PB7 1,使用GPIO口直接给OLED供电,OLED功率小,但不是很规范
C语言不支持直接写二进制的数
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
uint8_t KeyNum; //KeyNum在这里是全局变量
int main(void)
{
OLED_Init();
OLED_ShowString(1, 1, "WangMengYuan"); //字符用单引号括起''
OLED_ShowString(2,1,"so bang!!!");
OLED_ShowString(3,1,"CHEER FOR");
OLED_ShowString(4,1,"SPORT MEETING");
// OLED_ShowNum(3,1,12345,7);
// OLED_ShowSignedNum(3,9,-77,2);
// OLED_ShowHexNum(4,1,0XAA55,4);
// OLED_ShowBinNum(2,1,0XAA55,16);
//OLED_Clear();
while(1)
{
}
}
我给小王的应援哈哈哈!!!?
中断系统和外部中断
- 中断系统——管理和执行中断的逻辑结构,
- 外部中断EXIT——众多能产生中断的外设之一
- 程序中的中断函数,其地址是由编译器来分配的,不固定的
- 中断跳转——硬件限制——只能跳到固定的执行程序
- 为了使硬件跳转到一个不固定的中断函数中——solution——需要在内存里定义一个地址的列表——列表地址固定,中断发生后,跳到这个固定位置——编译器+一条跳转到中断函数的代码——》中断跳转可跳到任意位置
中断地址的列表——中断向量表——中断跳转的跳板
NVIC——嵌套中断向量控制器——统一分配中断优先级和管理中断(叫号系统)
内核外设,CPU(医生)小助手
?插队看病——响应优先级
决定是不是可以中断嵌套的优先级——抢占优先级
第一个病人——EXTI外部中断
为什么这四个要来外部中断蹭网呢??
外部中断有个功能——从低功耗模式的停止模式下,唤醒STM32
中断响应与事件响应
- 中断响应:申请中断,让CPU执行中断函数
- 正常流程,引脚电平变化触发中断
- 事件响应:对外部中断增加的一种额外功能,当外部中断检测到引脚电平变化时,正常流程选择触发中断,在STM32中,也可选择触发一个事件——外部中断信号不会通向CPU,而是通向其他外设,用来触发其他外设的操作,例如:触发ADC转换、触发DMA
- 不会触发中断,而是触发别的外设操作,属于外设之间的联合工作
AFIO——数据选择器
- 在前面GPIO外设的16个引脚里选择其中一个连接到后面的EXTI通道中,可以解释《支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断? ——例如:PA1、PB1、PC1不可同时使用,只能选择一个作为中断引脚)》?
- 即所有的GPIO口都能够触发中断,但相同的Pin不能同时触发中断的原因。
配合外部中断我们所要选择的硬件模块
- 什么样的设备需要用到外部中断?
- 使用外部中断的好处?
使用外部中断模块的特性:
1、对于STM32来讲,想要获取的信号时外部驱动很快的突发信号(突发信号——STM32不知道信号什么时候到来)
2、它是外部驱动的,STM32只能被动读取
3、此信号非常快,STM32稍微晚一点读取,就会错过很多波形
有脉冲过来,STM32立即进入中断函数处理,没有脉冲时,STM32就专心做其他事情
一些注意的点:
- 红外遥控接收头的输出——接收到遥控数据后,会输出一段波形,转瞬即逝,不会等你——solution——用外部中断来读取
- 按键——其动作也是外部驱动的突发事件,但不推荐使用外部中断读取按键——why——因为用外部中断不好处理按键抖动和松手检测的问题,且对于按键来说,其输出波形不是转瞬即逝,要求不高,可以在主程序中循环读取或者定时器中断读取——advantage——既可以后台读取按键值、不阻塞主程序,还可以很好处理按键抖动和松手检测
旋转编码器:
通过B相是滞后还是超前A相90°,来判断其正转还是反转
相位相差90度的波形——正交波形
带正交波形信号输出的编码器——可以用来测方向
单相输出和两相正交输出
5-1 对射式红外传感器sensor计次
外部中断的配置流程
- 涉及外设——RCC/GPIO/AFIO/EXTI/NVIC
- ? ? //1.初始化打开时钟,使外设工作?
- ?? ?//2.配置GPIO,选择我们的端口为输入模式
- ?? ?//3.配置AFIO,选择我们用的这一路GPIO,连接到后面的EXTI
- ?? ?//4.配置EXTI,选择边沿触发方式、触发响应方式
- ?? ?//5.配置NVIC,给中断选择合适优先级,通过NVIC,中断信号进入CPU,CPU才能收到中断信号,才能跳转到中断函数中执行中断程序
- EXTI、NVIC两个外设,其时钟是一直打开的,不需要我们再开启时钟了
- EXTI作为独立外设按理说是应该需要开启时钟的
- NVIC是内核外设——内核外设无需开启时钟,内核外设和CPU一起住在皇宫里
- RCC管的都是内核外的外设
现在进入程序模块的编写?
GPIO的外设重要函数:
- 364——进行引脚重映射,
- 365——配置AFIO的数据选择器,来选择我们想要的中断引脚?
?主程序中查看、清除标志位:
一般的读写标志位,没有额外的处理,能不能触发中断的标志位都能读取?
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);
void EXTI_ClearFlag(uint32_t EXTI_Line);
?在中断函数里查看和清除标志位:
只能读写与中断有关的标志位,并且对中断是否允许做出判断
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
?本质上,以上四个函数都是对状态寄存器的读写
?优先级在多个中断源同时申请,产生拥挤时才有作用
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
?抢占优先级和响应优先级都设置为1,这里只有一个中断,优先级就随便了
在STM32中,中断函数的名字都是固定的,每个中断通道对应于一个中断函数,中断函数的名字可以参考启动文件
- 以_IRQHandler结尾的名字——中断函数的名称,中断函数名可千万不要写错,写错了就进不了中断了。
- 中断函数里,先进行中断标志位的判断——确保是我们想要的中断源触发的函数,在此程序中,EXTI10—EXTI15都能进来,——所以判断是否是我们想要的EXTI14进来的
- 中断函数不需要声明——因为中断函数不需要调用,它是自动执行的
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"
uint8_t KeyNum; //KeyNum在这里是全局变量
int main(void)
{
OLED_Init();
CountSensor_Init();
OLED_ShowString(1,1,"COUNT:");
//OLED_Clear();
while(1)
{
OLED_ShowNum(1, 7, CountSensor_Get(), 5);
}
}
但实验结果是——我遮一下有时会增加近10次,弹幕有人说——换一个好一点的遮光片
5-2旋转编码器计次
?前期准备:A、B相都触发中断
?老师一点关于中断编程的建议:
- 1.在中断函数中,最好不要执行耗时过长的代码,中断函数要简短快速,别一进中断就delay_ms(),
- 中断是处理突发事件
- 2.不要在中断函数和主函数调用相同的函数——尤其是硬件显示函数(例如:OLED显示函数)或者操作同一个硬件
- 问题出现在中断结束之后——需要继续原来的显示,好了!出问题了!——》硬件的显示位置被挪到了其他地方,再回来时,继续显示的内容就会跟着跑到其他地方去。虽然在中断进入和退出时,会有保护现场和恢复现场——只能保证CPU程序能正常返回不出问题,对于外部硬件,并没有在进入中断时,进行现场保护,——》所以,中断返回后,出现问题
- 避免此问题——最好不要在主程序和中断程序里,操作可能产生冲突的硬件——实现功能时,在中断里操作变量或标志位,当中断返回时,再对此变量进行显示和操作——既保证中断函数的简短、快速,又能保证不产生冲突的硬件操作
- 以及在其他地方,也都可以多使用变量和标志位——减少代码的耦合性,让各部分间代码相互独立,仅使用变量、标志位或者函数作为接口,——advantage——让程序更加清晰,代码更加强健
|