目录
目录
第1章软件配置
1.1FlyMcu下载工具配置
1.2 STM32——ST-Link v2调试下载器的连接方法
1.3如何选择芯
1.4 ATKXCOM配置
第2章 知识点合集
2.1 N.定义
2.2 编译疑问
2.2.1 GPIO函数推挽疑问
2.2.2 跑马灯工作原理是什么
2.2.3 端口解答
2.2.4 波特率怎么计算
2.2.5 why写两个模式--推挽&浮动
2.2.6 BUF引出疑问--寄存器和存储器的区别
2.2.7 USART_DR&USART_RD有什么区别
2.2.8 二进制->十六进制转换用什么口诀
2.2.9 下图中APB2是什么意思
2.2.10 下图中USAT1_IRQn是什么意思
2.2.11 下图中extern有什么特点
第3章 实战
3.1实战1LED灯点亮
3.1.1考察点
3.1.2 设计流程
3.2实战2 串口寄存器
3.2.1考察知识点
3.2.2实验步骤
3.3实战3 串口通信寄存器
第4章 培训简记
4.1 IDR输入数据寄存器
4.2课后问题
4.3需解答的问题
4.3.1 延时问题
4.3.2 优先级数据会给吗
4.3.3 与运算
4.3.4usart_rx_star&0x8000什么意思
1.3如何选择芯
ATK打开串口失败!!!,或其它错误。请选择正确的串口或该串口被占用
2°检查COM口是否冲突
解决方法: 将冲突COM口改为其他COM口号
步骤:
1、打开此电脑,点击管理
2、打开计算机管理后,打开设备管理器。
3、右键点击冲突COM口,选择属性
4、选择端口设置,点击高级
5、更换端口号并确定即可
1°
答:∵HAREWARE文件中非空
method:清空HAREWARE文件
2°
uVision
Error: Flash Download failed - Target DLL has been cancelled
错误:闪存下载失败 - 目标 DLL 已被取消
Case:项目打开太多
Method:全部关闭,重新打开
1.6C语言文件编译报错
.\HAREWARE\KEY\KEY.c(33): error: #136: struct "
.Case:类型端口错误,少了一个初始化定义
Method: 将GPIO_TypeDef改为GPIO_InitTypeDef
1.7 提示对象未定义怎么办
答:因为花圈处未写,去对象头文件里面查找问题
1.8 提示符号问题怎么办
第2章 知识点合集
2.1 N.定义
(1)clock:时钟
(2)u8:代表无符号8位的数据类型
(3)translate:运输;rebuild:重建;batch build:批量生成
(4)USART:即串口(通用同/异步接收器:Universal Synchronous/Asynchronous Receiver/Transmitter)
(5)CR:控制寄存器(Control Register)
(6)RDR:接收数据寄存器
(7)USART_DR:串口的收发双寄存器( TDR&RDR)
(8)USART_SR:状态寄存器
(9)TC :发送完成
(10)USART_Cmd(USART1, ENABLE):串口使能函数
(11)Parity:奇偶校验
(12)查找参数出错提示信息(browse information:浏览信息;available:可用的)
(13)KEIL下载失败提示信息(target:连接)
(14)USART1 - >DR=USART - RX - BUF[t]中BUF什么意思:数据存储器
(15)当在双等号运算符中,0:低电平,无电压,∴灯不亮
注意:当是=赋值时,0表示开,1表示关
(16)CNF和MODE:TM32的CRL控制着每个IO端口的位占用CRL的4个位,高两位为CNF,低两位为MODE。
拓展:CRH的作用和CRL完全一样,只是CRL控制的是低8位输出口,而CRH控制的是高8位输出口
悟:01就是开关,控制引脚的开关,为一则为打开通电∴为1时接收新数据,为0则无变化(一般只用低16位)
(16)flow:流(USART_HardwareFlowControl中断硬件控制流)
(17)Bound:波特率
(18)Config:配置(USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断 )
(19)peripheral:外设(RCC_APB2PeriphClockCmd)
(20)Flash Download failed:闪存下载失败
(21)IWDG_KR:键值寄存器
2.2 编译疑疑惑
2.2.1 什么是GPIO
GPIO(general porpose intput output):通用输入输出端口的简称。可以通过软件控制其输出和输入。stm32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通信,控制以及数据采集的功能。
2.2.2 跑马灯工作原理是什么
2.2.3 端口解答
2.2.3.1 什么是端口复用
1.什么是端口的复用?
stm32中的许多内置外设,这些外设的外置引脚都是和GPIO共用同一个端口,一个GPIO口如果可以作为某个内置外设的引脚,那么当GPIO口作为内置外设的引脚使用时,就叫做端口的复用。
例如:串口1的引脚对应的Io口为PA9,PA10,PA10的默认功能是GPIO。PA9,PA10引脚作为串口1的TX,RX引脚使用时,就是端口复用
注意:串口对应引脚怎么找?
答:根据芯片查找串口对应的复用引脚--串口1的接收与发送对应的复用引脚位PA8,PA9
2.端口的复用的准备工作
端口复用初始化需要如下三步:
1.GPIO端口的使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
2.复用的外设时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
3.端口模式配置
例如:将PA9的模式配置为复用推挽输出:
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure); //配置PA9的模式
3.我们在使用复用功能时,最少使能2个时钟:
1)GPIO时钟使能
2)复用的外设时钟使能
2.2.3.2 什么是端口重映射
1 端口重映射
每个配置都有若干个输入输出引脚,一般这些引脚的输出端口都是固定不变的,为了让设计工程师可以更好的安排引脚的走向和功能,在stm32中引入了外设引脚重映射的概念,即一个外设的引脚除了具有默认的端口外,还可以通过设置重映射寄存器的方式,把这个外设的引脚映射到其他的端口。
为了使不同器件封装的外设IO功能数量达到最优,可以把一些复用功能重映射到其他一些引脚上。
STM32中有很多内置外设的输入输出引脚都需要重映射的功能。
2 I/O端口的重映射技术的需求背景
1.I/O的复用:GPIO和内置外设共用引出管脚
2.I/O的重映射:复用功能(AFIO)从不同的GPIO管脚引出
3.方便PCB的设计,潜在的减少了信号交叉干扰
4.分时复用某些外设,虚拟地增加了端口数目
3 AFIO重映射的操作步骤
1.使能被重新映射到的I/O端口时钟
2.使能被重新映射的外设时钟
3.使能AFIO功能的时钟
4.进行重映射
注意:哪些情况需要开启AFIO辅助功能时钟?
4 部分重映射&完全重映射
部分重映射:功能外设的部分引脚重新映射,还有一部分的引脚是原来的默认引脚
完全重映射:功能外设的所有引脚都重新映射
5 引脚重映射的配置过程!!!!!
1.使能GPIO时钟(映射后的时钟)
2.使能功能外设时钟(例如串口1)
3.使能AFIO时钟。重映射必须使能AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
4.开启重映射
GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);
6那些情况下需要开启AFIO辅助功能时钟?????
对寄存器AFIO_MAPR\AFIO_EXTICRX\AFIO_EVCR进行读写操作前,应当首先打开AFIO时钟
AFIO_MAPR:配置复用功能重映射
AFIO_EXTICRX:配置外设中断线映射
AFIO_EVCR:配置EVENTOUT事件输出
2.2.3.3 why引脚写两个模式--推挽&浮动
索引:什么是推挽
主要作用:增强驱动能力,为外部设备提供大电流
推挽输出运行过程:用两个晶体管或者场效应管构成的推挽电路(在模拟电路中应用很广泛如功放驱动电机驱动等等),这个电路的特点就是输出电阻小,所以能够驱动大的负载,从而能够使得单片机管脚直接驱动发光二极管、蜂鸣器、甚至更小阻抗的负载!
why引脚写两个模式--推挽&浮动
答:因为要配置端口输入和输出:
1、详解TX(PA9)管脚需要配置为推挽复用输出;
RX(PA10)管脚配置为浮空输入或者带上拉输入。
表1 串口 GPIO 模式配置表
2、需要注意一点,如果使用到了串口的中断接收,必须在 usart.h 里面设置EN_USART1_RX 为 1(默认设置就是 1 的) 。该函数才会配置中断使能,以及开启串口 1 的NVIC 中断。这里把串口 1 中断放在组 2,优先级设置为组 2 里面的最低。
接下来还要编写中断服务函数。串口 1 的中断服务函数 USART1_IRQHandler 。
3、重点拓展看下mian()函数中的以下两句:
USART_SendData(USART1, USART_RX_BUF[t]); //向串口 1 发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
句一是发送一个字节到串口。句二呢,就是我们在我们发送一个数据到串口之后,要检测这个数据是否已经被发送完成了。 USART_FLAG_TC 是宏定义的数据发送完成标识
2.2.5 图中PA9端口是如何确定的
答:根据工程对象决定,如实现串口1的中断,则查看原理图进行查找引脚
串口1的发送数据引脚
拓展:引脚是如何选定?
答:根据实验目的可得,如:串口实验肯定选串口引脚
拓展:引脚知道了,根据《stm32参考手册》搜索引脚就可找到对应输入输出模式
2.2.6 BUF引出疑问--寄存器和存储器的区别
寄存器存在于CPU中,速度很快,数目有限,计算机做运算时,必须将数据读入寄存器才能运算。;
存储器(RAM&ROM)就是内存,速度稍慢,但数量很大;
2.2.7 USART_DR&USART_RD有什么区别
(2)USART_RD 读取数据
Eg:usart_rd_len=0; //数据长度清零
2.2.8 二进制->十六进制转换用什么口诀
8421法
将二进制数的每4位分隔开,则是与这4位分别一一对应,0代表无这个数,1代表有这个数,将分割的每4位获得的数相加,最后将每4位的结果加起来就成了16进制啦!
注:从后往前分割,不够4位向前补0
2.2.9 下图中APB2是什么意思
答:使能固定端口,下图是使能固定格式
2.2.10 下图中USAT1_IRQn是什么意思
答:USAT1_IRQn是中断通道,接下来中断优先级对其进行分组,中断通道格式如下图
2.2.11 下图中extern有什么特点
.h中的extern表示串口接收的最大字节长度在外部usart.c定义
usart.h文件
usart.c文件
2.2.12 延时问题
1延时问题:delay位置不同的集中情况(1°两个参数都实现效果2°只出现一种参数效果)
比如:
两个点亮时长5000ms,第一个灯不受延时5ms的影响,但当两值对调时,各值都会实现各自效果
解答:正常不会这样分开设置
答:为了让电平稳定,因为按键按下会有高电平出现
2.2.13 优先级数据会给吗
2.2.15 按键对应电流思维纠正
以上四个按键所对应的管脚编号分别为:PA0、PE4、PE3、PE2。由图可知,KEY_UP为高电平有效,其他三个均为低电平有效。
2.2.16 引脚表格使用指导
GPIOB之所以为00000008,是因为对应的二进制为1000,运用“8421法”将二进制转化为十六进制正好为8
2.2.17 if…else if…else 判断语句
一个 if 语句后可跟一个可选的 else if…else 语句,这可用于测试多种条件。
当使用 if…else if…else 语句时,以下几点需要注意:
一个 if 后可跟零个或一个 else,else 必须在所有 else if 之后。
一个 if 后可跟零个或多个 else if,else if 必须在 else 之前。
一旦某个 else if 匹配成功,其他的 else if 或 else 将不会被测试。
格式:
if(boolean_expression)
{
/* 如果布尔表达式为真将执行的语句 */
}
else
{
/* 如果布尔表达式为假将执行的语句 */
}
Eg:
#include
int main ()
{
/* 局部变量定义 */
int a = 10;
/* 使用 if 语句检查布尔条件 */
if( a < 20 )
{
/* 如果条件为真,则输出下面的语句 */
printf("a 小于 20\n" );
}
printf("a 的值是 %d\n", a);
return 0;
}
拓展:
(0)if 语句:一个 if 语句 由一个布尔表达式后跟一个或多个语句组成
(1)if…else 语句:一个 if 语句 后可跟一个可选的 else 语句,else 语句在布尔表达式为假时执行
(2)嵌套 if 语句:你可以在一个 if 或 else if 语句内使用另一个 if 或 else if 语句
(3)switch 语句:一个 switch 语句允许测试一个变量等于多个值时的情况
嵌套 switch 语句 您可以在一个 switch 语句内使用另一个 switch 语句
2.2.18 switch...case条件语句
语法:
switch(值){
case 值1:
匹配值1
case 值2:
匹配值2
注意:
(1)Case:只要匹配上,则其他case不再进行匹配,直接顺序执行所有的代码。直到遇到break或者整个结束
(2)default:没有具体的值,除了其他的case都不匹配,则匹配default,用法同case;位置一般推荐最后,其他位置也可以,注意要不要加break
(3)break:跳出整个switch语句
(4)值类型:int,byte,short,char,字符串,枚举enum
if。。else 和switch…case
if语句可以做等值判断,也可以做区间判断
switch语句只能做等值
在做等值判断时两种可以互换
嵌套
嵌套符合语法结构即可
if(){}
if(){}else{}
switch(){case:}
以上结构固定
嵌套考虑条件
import java.util.Scanner;
public class Regist {
public static void main(String[]args) {
Scanner input = new Scanner(System.in);
System.out.println("欢迎来到个人博客!");
System.out.println();
System.out.println();
System.out.println();
System.out.println("1.已有账号,登录\n2.注册新账号\n3.退出系统");
System.out.println("请选择:");
int choose = input.nextInt();
switch(choose) {
case 1:
System.out.println("输入用户名:");
String name = input.next();//name 在switch中
System.out.println("输入密码:");
String pass = input.next();
if (name.equals("张三")&&pass.equals("zhangsan")) {
System.out.println("1.查看用户信息\n2.修改密码\n3.充值");
} else {
System.out.println("用户名或者密码错误,请重新登录");
}
break;
case 2:
System.out.println("输入用户名:");
String name1 = input.next();
System.out.println("输入密码:");
String pass1 = input.next();
System.out.println("请确认密码:");
String pass2 = input.next();
if (!name1.equals("张三")&&pass1.equals(pass2)) {
System.out.println("注册成功,请登录");
} else if(name1.equals("张三")){
System.out.println("用户名重复");
} else {
System.out.println("密码不一致");
}
break;
case 3:
break;
default:
System.out.println("输入有误请输入1 ~ 3");
return;
}
}
}
变量作用域
定义的一个变量,从定义的地方开始,到所在的代码块(大括号)结束。
从定义开始,到结束,也就是说在一个变量的作用域内,不能定义重复的变量。
出了作用域的变量将不能在使用
2.2.19 通信接口的背景知识
2.2.20
2.2.x 运算疑惑
(1) 符号“与”的意义
0020|0040=0010|0100=0110即将值寄存,想调用某值直接调用寄存器即可
(2) 0x8000什么意思
答:usart_rx_star&0x8000中0x8000是串口收到的数据为1000 0000 0000 0000,即最高位为1,其他位为0
(3) && 和|| 优先级问题
运用数字、布尔值、字符串验证与、或的优先级?
举例:
123||“abc”&&true; //123
“abc”||123&&true;//abc
true||123&&“abc”;//true
123||true&&“abc”;//123
true&&“abc”||123;//abc
“abc”&&true||123;//true
总结:&&的优先级高于||的优先级;
记住: 先‘与’再‘或’,对于表达式逻辑理解能够更清楚;
补充:括号()的优先级最大,(123||true)&&“abc”; //“abc”,先括号再与
拓展:运用数字与布尔值去验证二元?
123 || true; //123
true||123; //true
123&&true; //true
true&&123; //123
规律:|| 的最终值在前 ,&&的最终值在后
(4)static:具有记忆功能的静态局部变量,只会在第一次被执行
本例以GPIOx_CRL为基地址,(纵向)偏移4位得GPIOx_CRH
第3章 实战
3.1实战1LED灯点亮
3.1.1考察点
3.1.1.1宏定义
define 是 C 语言中的预处理命令,它用于宏定义,可以提高源代码的可读性,为编程提供
方便。
常见的格式: #define 标识符 字符串
“标识符”为所定义的宏名。
“字符串”可以是常数、表达式、格式串等。
例如:
#define SYSCLK_FREQ_72MHz 72000000
定义标识符 SYSCLK_FREQ_72MHz 的值为 72000000。
3.1.1.2时钟使能
RCCReset clock control--控制提供给各模块时钟信号的通断
例如:RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOB,ENABLE);
3.1.2 设计流程
1.头文件写宏定义和函数声明
(查找区域:
A.
B.
得
)
C.声明端口结构体
D.为结构体添砖加瓦添加参数:结构体名+点
注意:若加点不弹提示,删除重新加点即可
注意:点击属性进行F12查找参数,若不行点击如下GPIO_Init
强调: PE5配置与PB5方法和参数都一样
3.获取电平进行点亮
Gpio.h中查找set
PB5&PE5获得高电平通电
4.写main函数
引入stm,声明main函数,添加对象设置无线循环语句,
再引入delay.h初始化函数,设置延时延时为了查看LED灯不同的效果,否则一直亮
3.2 实战2 蜂鸣器
3.2.1工作原理:蜂鸣器两端通电,出现压差蜂鸣器就会发声
3.2.2引用三极管的原因:为了提高电平∵IO不能直接驱动大功率蜂鸣器
3.2.3 下载失败原因:项目打开过多、未引入C语言文件、ST-Link部分接口脱落、ST-Link未配置
3.3 实验3 按键输入实验
#按键模块电路图
我手中的开发板除去复位按键后还有其余四个按键,电路结构图如下:
以上四个按键所对应的管脚编号分别为:PA0、PE4、PE3、PE2。由图可知,KEY_UP为高电平有效,其他三个均为低电平有效。
实验总结
(1)头文件编译步骤
宏定义、引入调用文件+宏定义读取按键输入函数(GPIO_ReadInputDataBit)+宏定义按键赋参
(2)C语言文件编译步骤
引入调用文件+端口配置+按键扫描函数(条件判断语句)
引入文件+主函数(对象初始化+while循环语句+if……else判断语句+switch……case条件语句)
补充:break跳出循环,开始新的循环
3.4实战4 串口寄存器收发数据
3.4.1考察知识点
考察抢占优先级(范围0-3),数值越小所代表的优先级就越高。
3.4.2实验步骤
答疑解惑
(1)why用按键
答:因为需要复位键控制程序执行
3.5 实战5 外部中断
强调:
需要说明的是因为我们的 WK_UP 按键是高电平有效的,而KEY0 和 KEY1 是低电平有效的,所以我们设置 WK_UP 为上升沿触发中断,而 KEY0 和 KEY1
则设置为下降沿触发。
3.5.1 1个串口最多可以连接几个端口
答:7个
3.5.2 GPIO 与中断线的映射关系的怎么来实现
答:所有函数 GPIO_EXTILineConfig()函数来实现
Eg:
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);
3.5.3 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;啥意思
答:
EXTI_InitStrue.EXTI_Trigger=EXTI_Trigger_Falling;//选下降沿
EXTI_InitStrue.EXTI_Mode=EXTI_Mode_Interrupt;// 触发中断
3.5.4 delay_ms(10)为什么是消抖,不是延时吗
答:短暂延时即为消抖
什么是抖动?
由于机械触点的弹性作用,一个按键开关在闭合时不会马上就稳定的接通,在断开时也不会一下子彻底断开,而是在闭合和断开的瞬间伴随了一连串的抖动。
因为抖动时间是由按键的机械特性决定的,一般都会在10ms以内,为了确保程序对按键的一次闭合或者一次断开只响应一次,必须进行按键的消抖处理。
3.5.5 LED0=0; 为什么低电平点亮 LED0
答:因为按键0&1是下降沿特性,key_up是高电平触发效果
实验三大模块总结:
C语言文件编译分为两大部分
A.引入文件
B.函数体进行配置
1.初始化结构体
2.时钟使能
3.端口配置
4.输出电平
头文件编译特点:
宏定义+函数初始化
主函数编译特点:
引入文件+初始化主函数(函数体内为函数表达式)