薪火培训电控第一讲——单片机与GPIO
@
文章参考:
【STM32】STM32F4 GPIO八种模式及工作原理详解
2021北京理工大学机器人队第四届薪火培训 电控部分——单片机与GPIO
【SUES木鸢机甲工作室】RoboMaster电控组基础培训——单片机基础
关于单片机
初识单片机
相信很多同学第一次看到“单片机”这个字眼的时候都不是很清楚其具体含义,上百度一查,看到类似下面的晦涩语句:
单片机也被称为单片微控器,属于一种集成式电路芯片。在单片机中主要包含CPU、只读存储器ROM和随机存储器RAM等,多样化数据采集与控制系统能够让单片机完成各项复杂的运算,无论是对运算符号进行控制,还是对系统下达运算指令都能通过单片机完成。 由此可见,单片机凭借着强大的数据处理技术和计算功能可以在智能电子设备中充分应用。简单地说,单片机就是一块芯片,这块芯片组成了一个系统,通过集成电路技术的应用,将数据运算与处理能力集成到芯片中,实现对数据的高速化处理。
其实,要想快速地理解一个东西最好的方法是看一看这个东西长什么样子,应用是什么,怎么用它。
至于理解,最好是一边使用一边进行。
下面这枚黑色小方块,就是所谓的单片机,就像前面百科说的那样,其实就是一块芯片,芯片周围有根据芯片型号数量固定的引脚
常用的STM32F103C8T6,有48个引脚
但是这些引脚太细,太脆弱(易折断),为了便于初学者进行学习,我们一般是使用开发板
单片机上很多外设,建议是用到什么学什么,“在战争中学习战争”,不过,在踏入外设使用这道门之前还有一个概念需要理解,那就是时钟
时钟
时钟可以简单理解为像单片机的心脏,每跳动一下,单片机各个电路就同步运行一下。只要单片机接上了电,无论单片机处于什么状态(跑进while(1),进回调……),时钟总是以一定的频率在运行。
时钟的频率是通过高低电平来实现的,它决定着单片机运行的快慢,我们总是希望时钟越快越好。
时钟的信号源并不是单片机自动配置好的,须知参差多态乃是STM32好用的根源,我们可以根据内部/外部 以及 低速/高速这两个方面来进行时钟的选择。一般情况下,我们会选择外部高速时钟,它频率高,同时也更稳定
至于时钟选择如何在软件中操作,那便是下面的事了,这里暂且不表
GPIO简介
GPIO的全称:General Purpose Input/Output
简单地说,就是控制某个引脚进行输入的读取和输出的高低电平设置嘛
general,就代表着这是一个相当基础的功能,很多功能其实通过GPIO也是能够实现的,狂风起于青萍之末,我们从最简单的开始学起。
GPIO函数
我们使用的Cube能够帮我们自动生成很多代码,因此我们就介绍几个与输入输出有关的函数
函数名 | HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) |
---|---|
作用 | 读取引脚输入电平高低 |
返回值 | 输入电平高低情况,GPIO_PIN_SET(高电平,真实值为1),GPIO_PIN_REST(低电平,真实值为0) |
参数 | 引脚基本信息,若选择引脚为PA14,那么函数可表征为:HAL_GPIO_ReadPin(GPIOA,GPIO_Pin_14); |
函数名 | HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) |
---|---|
作用 | 设置引脚输出电平高或低 |
返回值 | 无 |
参数 | 前两个与Readpin基本相似,最后一个PinState就是选择要设置的电平高低(就是readpin的返回值) |
函数名 | HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) |
---|---|
作用 | 翻转某个GPIO引脚的电平状态。如果为0则变为1;如果为1则变为0 |
返回值 | 无 |
参数 | 引脚基本信息,若选择引脚为PA14,那么函数可表征为:HAL_GPIO_ReadPin(GPIOA,GPIO_Pin_14); |
八种输入输出模式
GPIO的八种模式的实现原理已经有大佬写得很详细了
【STM32】STM32F4 GPIO八种模式及工作原理详解
不过其软件方面没必要学习,链接里使用的是标准库,而我们使用的是HAL库
在这里我就给一个简单的理解
模式 | 说明 |
---|---|
浮空输入 | 在无输入的情况下读取值不确定 |
上拉输入 | 无输入默认高电平 |
下拉输入 | 无输入默认低电平 |
模拟输入 | 读取值为模拟信号,需要额外开ADC |
开漏输出 | 输出的高电平高低取决于IO口外部电平上拉或下拉,低电平仍为低电平 |
推挽输出 | IO口电平即为输出的电平 |
复用开漏/推挽输出 | GPIO启用其他外设,除了输出信号的来源改变 其他与开漏/推挽输出功能相同 |
不过需要说明的是,我们平常使用GPIO,保持默认其实能够满足大部分需求
Cube和keil使用简介
使用cube建立项目
keil使用
贴一个keil快捷键的使用那些快捷键不香吗?无能KEIL 其二 快捷键
相信很多大一的同学看到keil这么多代码头都要晕了
不过不要害怕!我们是站在巨人的肩膀上,cube帮我们生成了很多底层的代码,我们暂时可以不用去管它
就目前而言,我们只需要在main函数的while(1)中写我们的内容即可
作业讲解与点评
作业的前两项,其实就是为了让大家复习一下这节课学习的东西,无所谓多少,无所谓质量,只要做了就行
第三项作业就是比较难的了(相对而言),也是希望大家拥有能够自学的能力,在听我们第二节课的时候能够轻松一点。组长也一再强调希望作业能够难一点,所以我就直接把我们第二节课的内容搬了一点上来。
讲解
ok,那就先来讲解一下这份代码
首先看看我写在main函数之外的函数duty_output:
void duty_output(float duty){
if(duty<0||duty>1000)return;
for(int i=0;i<1000;i++){
if(i>duty)HAL_GPIO_WritePin(DEMO_GPIO_Port,DEMO_Pin,GPIO_PIN_RESET);
else HAL_GPIO_WritePin(DEMO_GPIO_Port,DEMO_Pin,GPIO_PIN_SET);
}
}
学过了今天的内容之后,相信大家对于这个函数实现的功能应该比较明白了,说白了就是通过GPIO输出一个pwm波。
我们GPIO只能够输出高电平和低电平,即0和1。可是生活中很多东西并不是非黑即白的,它很复杂。单片机也是这样。我们能输出0,1,这很好,但是万一要输出0.8,0.2这样的值呢?
为了实现这样的输出,pwm波算是一种途径,具体实现的方法学长有详细的讲解,大概就是某个时间段内的“有效电平”,1s内我有0.8s输出1,0.2s输出0,那么这1s内我的有效电平就是0.8。大概可以这么理解。
扯远了,回到作业内容,理解了duty_output这个函数,那么就只剩下while(1)中的语句了
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_9)==GPIO_PIN_SET&&!input_flag){input_flag=1;HAL_Delay(10);}//Hal_Delay(10)是为了避免按键消抖,这里判断按键是否被按下
if(!input_flag) HAL_GPIO_WritePin(DEMO_GPIO_Port,DEMO_Pin,GPIO_PIN_SET);//如果按键没被按下
else{//按键被按下
for(int i=0;i<900;i+=10) {duty_output(i);HAL_Delay(2);}
for(int i=900;i>0;i-=10) {duty_output(i);HAL_Delay(2);}}//呼吸灯
}
这边其实还整了一个花活,就连接一个按键到PA5,通过读取PA输入电平来判断按键是否被按下,若被按下切换为呼吸灯,如果一直保持不被按下的状态,则是常亮。其实按键来控制还有更高明的方法,更灵活,功能也更加强大,就是第三节课要将到的外部中断,有兴趣的同学可以预习一下。
至于呼吸灯,第二节课应该是讲过了,还有比较神奇的按键消抖,那就自行百度咯~
作业点评
大概有五分之一的同学能够正确写出“呼吸灯”或者“pwm”这样的字眼,其实写到这个份上应该算是回答正确,能够写出整体逻辑更好。(但是有的同学就写上三个字“呼吸灯”这让我有点手足无措,也不知道是不是真的搞懂了)
不过有的同学却误入歧途,讲解了SystemClock_Config,MX_GPIO_Init这些cube帮我们配置好的函数的作用,我们上课的时候不是说了嘛,这么多的代码在这个阶段我们不用很关注,只需要知道一般在哪里写就行,譬如你进我的项目先看看while(1),一看duty_output没有见过,那就右击选择go to definition看看这到底是个什么玩意儿,再稍微理解一下就差不多了。
前几天更新了一下cube,所以版本是最新的,大家估计因为版本低所以打不开,关系也不大,很多东西都在keil里,你不会升级cube,打开keil读读代码也行。但是就有好些个同学就写“打不开,没看”,这就让我们有点哭笑不得了。搞机器人本来就是“敢热爱,你就来”的科创,这种敷衍潦草的态度我深不以为然。
总结
电控第一讲到这里也就结束了
电控的入门比较艰难,可是一旦掌握了基础,在不断的实操中便能够得到精进
日拱一卒无有尽,希望大家能在不断的尝试中成就自我!