前言
对于0并无正负之分,之前我都对电子一无所知,因此也谈不上感兴趣与否。自这学期的电分模电开始才第一次对EE有了印象,感觉还蛮有意思。
十月份某日,Java老师提到他的网站是跑在作为服务器的树莓派上的,说者无心听者有意,我那时不知道脑子怎么一抽,对树莓派突然来了兴趣。那时我在写基于原生JavaWeb+Mybatis+Vue+ElementUI的文件管理系统,让我想到一个非常有意思的想法,如果有足够稳定的内网穿透服务,实现的效果会比组NAS更好而成本也低得多。在花了一点功夫之后,我成功用裸板149r的orangepi几乎完美实现了上述功能,具体细节参见上篇Blog。
玩过orangePi之后,对它几十个GPIO接口自然也有了兴趣,渐渐也对更底层的东西感到好奇。刚好那时学校里的电子爱好者协会在招新培训,再加上游园会上又在ICEC的摊子上焊接过双闪灯,经过一阵子的纠结,还是决定报名去参加了。
写到这里,想起来去年这时候也去参加安全相关实验室的培训了,果然我多半是个一事无成的人,发现有趣的事就忍不住去做。回想过去自己也一直是随性而为,不过我是不会后悔的,无论结果如何,都决不后悔自己经过思考作出的决定。我只要能够做感兴趣的事,能够思考就已经很幸福了。
硬件
电容
降压
利用电容的容抗实现降压电路,容抗公式计算如下:
但如果电容很大时,可能在电源断开后电容放电导致烧毁元件,因此需要根据容抗计算出并联电阻加在电容旁。
那么为什么不用电阻直接分压?电阻分压需要做功,且要发热,电容为无用功率。
滤波
滤波实际上也是利用容抗,即电容的通高频阻低频。
例如高通滤波器:
延时
电容两边的电压不能突变,电容充电可实现演示。
耦合
同样是通高阻低
旁路
在芯片旁接一个旁路电容,可使芯片免受高频信号干扰。
三极管
可作为小电流控制大电流的电气开关,也可作为放大器。
运算放大器
虚短+虚短可完成几乎所有计算。
IC芯片
仔细读芯片手册,研究每个引脚的作用即可。
实例1:双闪灯电路
利用两个三极管性质不可能完全相同,以及电容两侧电压不能突变,实现固定频率的双闪灯,如此简单的电路就实现震荡,实在很有意思。
实例2:循迹小车循迹模块
本以为是通过摄像头加图像处理实现的,结果非常非常简单的硬件模块就能完成:利用几个红外发射管与红外接收管实现的,不同颜色地面反射的红外线量不同,通过这种差别实现循迹。
根据接收管通断位置判断循迹的线位置,再用PWM波控制左轮或者右轮转速实现差速控制,就能完成转向和循迹。
嵌入式软件
对STM32单片机,最高效的开发环境为CubeMX + Keil5。
外部中断
检测外部按键需要用到上拉电阻或者下拉电阻,实现稳定的电平检测:
读取外部按键,调用相应的回调函数实现外部中断:
1 | void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin) |
实际上是覆盖了弱定义的HAL库函数。
计算机读取外部硬件信号都是使用外部中断的形式,但一个中断需要占用一个GPIO口,而GPIO口是有限资源,对于键盘这种需要大量中断的外设怎么办呢?答案是矩阵扫描
但这种扫描会造成鬼影之类的问题,因此实际是通过非常快的翻转row和column电平实现读取的,顺带一提,手机屏幕获取触屏位置也是类似的原理。
定时器
定时器实际上就是周期执行任务,具体频率需要经过仔细计算:
定时器的输入时钟频率,计算定时器Prc(Prescaler 预分频值)与Arr(AutoReload Register 自动重装载值)。我们默认将单片机主频率设置为64MHz,通过查看STM32G070RB芯片的数 据手册,可确定所使用时钟TIM7挂载在APB(Advanced Peripheral Bus[低速总线])总线上,因此其输 入时钟频率与APB总线上的频率一致,通过查看时钟树,可确定其输入时钟频率为64Mhz。
例如周期为1s时,主频律64Mhz,则取Psc = 6399, Arr = 9999。
中断开启定时器:
1 | HAL_TIM_Base_Start_IT(&htim7); |
同样需要重写弱函数:
1 | void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ |
定时器通常用于输出PWM波。
PWM波
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出!
利用PWM的频率和占空比可实现输出变化的电平——实际上是非常快速的改变占空比。
1 | while |
与上面的定时器合用可实现呼吸灯或蜂鸣器响度随时间周期性变化。
另外也可用于控制舵机,当然直接用32自带的PWM通道也可以。
串口通信
即UART协议通信,是最常用的单片机通信协议。
实际上就是通过约定的一串高低电平实现通信,例如UART就是八位,其中首位是通信标志位,当首位由低电平转为高电平时通信结束,这之间就是传输的数据。
一般通信需要用RX接TX,TX接RX完成。
软件层的通信定义与以中断模式开启UART(也可用DMA模式开启):
1 |
|
回调函数如下:
1 | void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) |
蓝牙通信与串口通信几乎没区别,只是需要设置波特率以及用AT命令模式自定义密码。
LCD屏幕显示
LCD使用SPI通信协议,实际上与串口没多少区别,一般用写好库直接调函数比较方便,但汉字输出只能取模,再定义在静态数组中调用了(图片显示也是一样的逻辑)。
1 |
|
写好库函数直接调用即可:
1 | LCD_Fill(26, 90, 42, 106,BLACK); |
但要对汉字提取取模定义:
1 | typedef struct |
ADC
即模拟信号转数字信号,多用于采集外部数据用于单片机分析。
DMA+ADC可实现高效的实时采集信息。
1 | HAL_ADC_PollForConversion(&hadc1, 50); //等待转换完成,50 为最大等待时间,单位为 ms |
项目:蓝牙 + 舵机实现自动关灯
1 | if((RxBuffer[Uart1_Rx_Cnt-1] == '!')&&(RxBuffer[Uart1_Rx_Cnt-2] == '!')) //判断结束位 |
配置好CubeMX实际上就是写蓝牙通信控制PWM舵机,再简单调试一下就搞定。