第一天与单片机基础知识:V1 | 您所在的位置:网站首页 › 单片机基础知识重点 › 第一天与单片机基础知识:V1 |
单片机基础知识
1.单片机中如何通过结构体(指针)来读写寄存器
知识:
GPIO寄存器地址就是偏移+首地址 关键:它是连续的 (每移位一次4字节) 结构体的成员地址也是连续的 定义int型(uint32_t,地址无符号)正好对上了每次移位4字节 让结构体首地址对上第一个寄存器地址,这样就可以通过结构体操作寄存器 注意:存储器映像(地址对应表),可以查看寄存器地址 考点:GPIO7个寄存器 因为:知道有多少个寄存器,定义结构体的时候就知道应该定义多少个成员 结构体对应上GPIO寄存器, typedef struct { uint32_t CRL; uint32_t CRH; uint32_t IDR; uint32_t ODR; uint32_t BSRR; uint32_t BRR; uint32_t LCKR; }My_struct; void test(void) { int a; a = (*((My_struct*)(0x40010800))).BRR; }或者宏定义更方便 常规定义: #define GPIO (*((My_struct*)(0x40010800))) void test(void) { int a; a = GPIO.BRR; }定义结构体指针,指针(地址)指向 #define GPIO (((My_struct*)(0x40010800))) void test(void) { int a; a = GPIO->BRR; } 2.C语言位域在单片机中的使用 代码.h文件: 单片机16个引脚 #ifndef __GPIO_H #define __GPIO_H #include "stm32f10x.h" //位域 typedef struct { volatile unsigned short bit0:1; volatile unsigned short bit1:1; volatile unsigned short bit2:1; volatile unsigned short bit3:1; volatile unsigned short bit4:1; volatile unsigned short bit5:1; volatile unsigned short bit6:1; volatile unsigned short bit7:1; volatile unsigned short bit8:1; volatile unsigned short bit9:1; volatile unsigned short bit10:1; volatile unsigned short bit11:1; volatile unsigned short bit12:1; volatile unsigned short bit14:1; volatile unsigned short bit15:1; }GOIO_Bit_Typedef; #define PORTB_Out ((GOIO_Bit_Typedef*)(&GPIOB->ODR)) #define PORTB_In ((GOIO_Bit_Typedef*)(&GPIOB->IDR)) #define PBout(n) (PORTB_Out->bit##n)//PortB_Out->bitn #define PBin(n) (PORTB_In->bit##n) #endifLed.c文件 #include "GPIO.h" void Led_Init(void) { PBout(13) = 1; PBout(13) = 0; } 3.什么是电平高低电平 0V-0.7V:0 2.2V-3.3V:1 低电平 高电平 CPU 输出 124D=0111 1100B 上升沿,下降沿 脉冲 两个低电平中间的高电平就是脉冲(上升沿+高电平+下降沿)010 4.单片机与寄存器 1.主要内容寄存器(任务书) ①.一般指的是:单片机它是指单片机外设相关的寄存器 ②CPU内部的叫做工作寄存器R0,R1.....PC指针,堆栈指针 ③RAM,外设(单片机内部模块),是处于CPU外部的硬件电路功能模块 单片机的引脚,工作模式两种:输入模式,输出模式 ④二进制,每一位2种状态 ⑤左移。&,| 懂寄存器: 1:首先搞清楚它的配置,二进制位配置,每一位都有其特定含义,了解其含义(主要根据宏定义学)。 2:每一位是具体是什么功能,到他前面看他的描述 为什么要学寄存器: 1.不是每个单片机都有库,不是每个人都有秘书帮你干活(公司、老板、总经理、总监),好多事情呢需要你自己去写一些八位单片机,还有一些16位一些低端的单片机。 无标准库和库函数,你只能通过寄存器来写。 2.老板说我们就需要一些便宜的单片机,有时候选择用什么单片机,不是你能选的 成本原因,老板说我们就需要一些便宜的单片机。 3.老工程师,就是用寄存器写,你要优化维护人家的代码,总不能写C语言吧,你没那本事也不敢。 老工程师的寄存器程序维护问题。 4.有些地方有寄存器比用库方便,懂寄存器肯定能懂库,库是寄存器的封装。 方便 难点: 其实就是首先你要对单片机它内部模块的工作原理你要懂,还有就是寄存器它后边的备注,就是它每一位表示什么意思 2.CPU与寄存器的关系:1. 将CPU比喻为皇帝,寄存器比喻为太监,寄存器外设比喻为大臣 RAM:针对当庭讨论事件的临时文件,主要用来方便沟通用退朝后就丢掉了。(草稿?) ROM:朝代制度,祖先、习俗规定等不可更改的。 2. CPU是厨师,寄存器是服务员,外设是菜单 菜单有啥厨师才能做啥;服务员负责点菜传菜,两者之间沟通; 5、如何看STM32单片机手册?需要啥?就看啥。 1、数据手册--硬件工程师 小、中、大容量三种 2、用户手册--软件工程师 统一小中大,只有一种 1.程序是如何下载的 2.电源是究竟是怎么一回事配合数据手册一起看 3.复位(上电、死机) 4.时钟信号 我们单片机就是一个数字电路,编程时: 首先第一步你要配置单片机的系统时钟,就像电脑一样你得配起来他的主频,让它的时钟能够正常运行,然后你才能让其他电路进行正常的工作。它是一个时序的电路。 5.RCC寄存器描述 这一部分我们可以看到有时钟控制,配置、中断,外设复位、使能。 使能:指始时钟使能,单片机为了控制功耗,它的时钟是可以开启和关闭的,当你没有开启相关电路的时钟的时候,这部分电路不工作的,功耗就低。 这些寄存器是干嘛用的? 6.单片机引脚、定时器、ADC、TIM、iic、spi,等等 介绍特点,它擅长干嘛功能,它具体能干嘛,如何干(重点看:功能框图)特点介绍(总体描述、内部结构可以知道有哪些功能)寄存器总结:用户手册,重点看功能框图,熟悉功能描述,稍微看一下寄存器,重点看状态寄存器SR 例如:你要单片机定时10s 1.单片机它是如何就是定时?=》使用定时器模块 2.定时器模块它为什么能定时?=》从用户手册发现,内部有一个叫做计数器的,它其实就是用来计时(计时时钟信号)的 3.单片机它是如何计数?=》从用户手册发现,如何计数 4.计算完10s,我又怎么知道?=》闹钟会响,手册发现它内部是有一个中断的(或者说标志位) 然后就是看这些东西怎么配置,完成你想要完成的功能。 从问题出发,单片机如何解决这个问题。大问题是多个小问题组成,由大到小,由小到大! 第一天 第1-1节:单片机入门与学习方法讨论 一、什么是嵌入式1、单片微型计算机简称单片机。微型控制器MCU(微型控制单元) 2、嵌入式系统是软硬件相结合的计算机系统,软硬件可裁剪。 3、常规性的定义:以应用为中心,以计算机技术为基础,软硬件可裁剪,满足对功能,可靠性,成本,体积,功能等严格要求的专用计算机系统。 二、嵌入式与单片机硬件: 单片机MCU、MPU、DSP、FPGA、CPLD 软件: 前后台系统(裸机程序) 、FreeRTOS、UCOS-II/III、Linux Nor Flash: 存放程序的储存器,断电不丢失数据 SRAM: 内存,存放数据的储存器,断电丢失数据 数据手册: 硬件工程师需要看的 用户手册: 软件工程师需要看的 三、学单片机需要的基础知识一、数字电路 1、数字电路相关的概念,名词。 2、组合逻辑电路,时序逻辑电路。 3、电平的概念,二进制,十六进制,十进制转换。 4、或门,与门,非门。常见的数字芯片74HC系列 二、模拟电路 1、二极管、三极管开关电、MOS开关电路 2、运放放大电路 (同相,反相,差分放大电路),电压比较器 3、电源电路 (3.3V,5V,12V电源稳压电路)、反馈电路 三、C语言 1、数据与类型 2、运算符 3、if switch while for 4、数组 5、函数 6、指针7、结构和联合 8、宏 四、学习单片机首先需要知道的事情1、单片机正常工作需要的基本硬件电路是什么? 2、使用什么软件写程序? 编程语言是什么? 3、如何把程序下载进单片机里面? 4、点亮一个LED,掌握单片机程序的项目工程 五、寄存器、标准库、HAL库1、其实没什么区别,都需要学习。严格来说,库不需要学,真正需要学的是单片机内部结构 2、C与算法 寄存器与单片机 3、单片机学习方法--实践出真知 学习初期:动手敲代码,别C+V别人的代码。 一遍看用户手册+看视频,一边自己写代码来验证自已理解的对不对 寄存器其实就是单片机的配置表(任务书),单片机如何工作,就根据寄存器里面的内容来进行工作的。 寄存器就是一个任务书,把单片机需要做的事情写进任务书(寄存器),然后单片机根据任务书(寄存器)去完成任务。 这就是编写程序的一个过程,我们需要把单片机要做的事情写进去这个过程其实就叫做初始化过程。 实践;反馈;理论; 在实践中丰富你的理论,纠正你的理论,你的理论指导你实践 第1-2节:STM32 单片机基本介绍STM32F103C8T6 用户手册: 数据手册: 关键参数C8T 48,64K,LQFR 不同容量都有自己的数据手册 但是用户手册呢它们是共用的 如何看? 简单总结:1;抓住一个关键(系统时钟SYSCLK) 2.看输入 3.看输出 关键: 抓住一个关键词叫系统时钟SYSCLK(最中心),跟我们电脑里面的主频是一个概念72MHZ, 输入: 系统时钟来自开关SW一共有三个: HSI内部时钟(内部的RC振荡器产生了8M时钟)、HSE外部晶振产生的时钟(最大4-16M)、PLLCLK锁相环时钟。 内部和外部的时钟太低,达不到72M,一般不用,我们一般用锁相环时钟(PLLCLK)。锁相环时钟前面有个倍频器(放大),乘“x”多少就放大多少倍。一般使用外部晶振产生的8M(内部的不稳定比如在比较冷的地方),然后开关PLLSRC选外部晶振,PLLMUL再选“x9”,8x9=72Mhz。然后在这边我们选择锁相环,中间这一路。 输出: AHB预分频器就是分频的(除号“/”降低频率),72不需要降,直接预分频选择一就是72÷1,出来之后是72。 通向:核心存储器和DMA; 通向:Cortex系统时钟:(你可以选择72MHZ八分频(9MHZ)或者不分) 1.系统定时器来产生一个中断,用来控制操作系统时间片的切换 2.写一个延迟函数 通向:CP的内核72MHZ 通向:两个总线时钟APB1,APB2 APB1,只能选择除以二(36MHZ),PCLK1是给APB1外设时钟:就是我们有一个外设,他的时钟源都是来自这里,所以我们在使用这些外设的时候,要开启它的时钟,这边有个外设时钟使能。 注意:所以STM32单片机,它有一个特点,你使用内部模块,你首先要把它对应的时钟要打开。一个与门,都为1才有效(这个时钟信号才是有效的)。 再往下APB1走,之前选两分频(分频系数不为1)要乘以二,也就是36×2=72,给到TIMXCLK定时器2-7,都是使用72兆的。 APB2同上分析。 APB2前走到ADC,ADC它其实是一个模数转换器,也需要时钟。这个时钟你可以选择(除以“/”,2、4、6、8),72÷6能达到12。除非前面输入56才能56÷4=14。 通向:最后AHB走到最后一根线,是SDIO的一个接口时钟 注意:低速内部时钟信号,使用的是32.768K,这个时钟一般是用来作为日历(内部RTC产生日历的) 然后,主时钟输出,单片机可以把它内部的时钟输出去(选一种);A单片机的MCO连到B单片机的OSC_IN(OSC_OUT接地) 只需要一个晶振可以给两个单片机,提供时钟信号 LQFP48:封装LQFP,引脚48 FT:引脚可以容忍5v电压 第2-1节:STM32单片机最小系统图1: 单片机、供电、晶振、复位、启动配置、下载端口 图2: 1引脚,备用电源电路 CR1220纽扣电池,工作电压3V,备用电源电路。 正常工作电源VCC3.3V,如果检测到输入电压为3.3V表示正常工作,输入为3V表示电源断掉。此时单片机会断开除了时间无关的电路,只保证时间正常。 3,4引脚,晶振电路: 两无极电容22pf+晶振32.768KHZ 5,6引脚,时钟电路 正常工作的时钟电路,晶振8MHZ+1M电阻+两个22pf无极电容 注:如果对时间要求不严格,可以使用单片机内部的RC震荡电路产生时钟信号 7引脚,复位电路 10K电阻+104无极电容+按键 按下按键电容短路,然后电容上端电压缓慢为0(接地),放手后又缓慢升上3.3V以此完成复位。 48脚单片机,四组电源(红色部分) VDD1 A(模拟) 要求不严格的情况下,可以将VDDA与三个VDD相连接都3.3V,并且将VSSA和三个VSS相连接都接地 以VDD2为例: 104无极电容主要作用电源滤波(电源有干扰),焊接电路电容尽量离两个引脚近一点,提高滤波效果 降压电路 USB供电,通过降压芯片(AMS1117-3.3)将usb的5v降到3.3v供电
28脚,验证工作指示灯 下载程序1 引脚(三根线) 下载与调试 下载器插座
一般ST-LINK接SWCLK/SWDIO 时钟线: 地线GND 下载程序2(串口下载电路) 2个引脚,输入/输出(RX/TX) 再加一个电源和地,4根线 把我们单片机的TTL电平转换成USB信号. 需要CH340G芯片(串口转USB芯片)进行电平转换
启动配置电路 一般直接BOOT1置0 BOOT0:0正常启动,1串口下载模式 第一天第2-2节:STM32程序下载方式介绍_哔哩哔哩_bilibili 参考: 第一天第3-1节:寄存器_标准库项目工程创建_哔哩哔哩_bilibili 寄存器和标准库
选中即可 GPIO(General Purpose Input Output)通用输入输出口,简称IO端口,也称单片机引脚。可以输入输出数据。 2、什么是电平?在数字电路中,电平是用来表达数字信号高低状态的一种方式,电平是用一段电压范围来表示的。 在数字电路中,只有两个电平,即高电平和低电平,又分别称作“1”和“0”。C语言中,二进制位的 数值也是1和0,刚好对应电路中的电平。STM32单片机供电电压VDD =3.3V。 0V-0.7V:0 2.2V-3.3V:1 3、STM32 GPIO简介GPIO有两大类模式:输出模式,输入模式 输出模式:控制IO引脚输出高低电平,可以用来控制外部设备或者输出数据。比如控制LED灯,继电器。输入模式:用来读取IO引脚的电平或者电压,也可以用来接收数据。比如,采集按键信息,外部的模拟电压。带FT标志的IO可以输入5V电压而不损坏,其他IO输入电压不能超过VDD (3.3V)单片机工作的总电流不能超过150mA,单个O引脚电流最大为20mA。上下拉电阻典型值为40K,最小值为30K,最大值为50K我们使用的,GPIOA、GPIOB。16+16=32个GPIO口 PA0-PA7:八个口在一起,这八个是模拟口,可以用来采集模拟信号 PA8-PA15:八个口在一起,并不能采集模拟,这边是数字信号的口 4、GPIO基本结构介绍位的基本结构:(单片机的端口它是由16位组成的) 输入驱动器:有上下拉电阻与浮空,以及模拟输入。触发器外部信号滤波(抖动变直线),如果要 采集模拟信号,把触发器关掉。 复用功能输入:其实也是一种数字信号,连接到单片机内部模块(数字模块),上面模拟输入是模 拟模块,数字模块它是可以直接通过触发器过来。复用功能:第二功能。 复用:多路开关123,通过寄存器拨到哪路,就是那个功能。 输入数据寄存器:通过这个电路,判断出是高电平还是低电平。高电平寄存器写1,低电平写0。最后读出数据。 输入驱动器:推挽、开漏,复用 复用:复用功能输出也是指的是数字复用功能 比如说我们输出一个PWM(脉宽调制,控制电机速度)本质上其实是一个方波,也是连接到定时器的(定时器模块连接到此) 读/写普通输出口:一个是直接输出数据寄存器进行操作,读/写,往输出数据寄存器写1,单片机这个I/O引脚就会输出3.3V。 写入位设置/清除寄存器:对单片机引脚位进行操作,往设置寄存器写1,输出数据寄存器它也会变成1。往清除寄存器写1,输出数据寄存器它也会变成0。设置清除同时写,按照设置寄存器写1处理。两个16位的寄存器拼接在一起成32位。 注意:输入输出两个寄存器是特别重要,输入数据寄存器,设置/清除寄存器。只要改变它中的内容,就会改变单片机引脚上的内容。 (推挽)输出控制:根据我们输出寄存器中的数据控制这两个mos管。设置寄存器1,输出控制给出一个信号,让下mos管关闭,上mos管打开,VDD通过上mos管,I/O引脚输出高电平。输出寄存器写0,则关上mos管,开下mos管,I/O引脚输出低电平。 注意两个箭头,如何到I/O口的然后输出,与从I/O口出来然后进入单片机。 开漏输出模式:上mos管永远关闭,只能控制下mos管。只能输出低电平。如果你要想输出高电平,只能在单片机引脚外部接一个上拉电阻,连接到VDD(引脚FT5v,否则3.3v)。如下图。 开漏输出好处:正常不能输出5V(只能3.3V),通过开漏外接的上拉电阻电源,就可以输出5V。 很多设备都是5V的,如果我们想要控制这些设备就得用开漏模式。 高电平:控制由P-MOS与PNP 低电平:控制由N-MOS与NPN 5、GPIO的8种工作模式输入:模拟,上拉,下拉,浮空 输出:推挽,开漏,复用推挽,复用开漏 复用连接的是内部模块(如定时器)
复用功能输出的时候,输出寄存器是不可控制。(ODR叫做数据输出寄存器,往里面写数据改变单片机引脚的电平) 输入:输入不存在什么速度配置的,单片机外部电路的信号能有不高,太快了单片机处理不过来就没有意义(MODE:00)。单片机默认情况下就是浮空输入。 ODR数据输出寄存器0,下拉输入(下拉电阻)。ODR数据输出寄存器1,上拉输入(上拉电阻)。ODR数据输出寄存器:区分上拉电阻和下拉电阻。 注意:在开漏模式时,对输入数据寄存器的读访问可得到I/O状态(既可以读也可以写,不需要切换到输入模式。推挽不能读) 宏定义:
GPIOx是一个结构体指针,指向GPIOx寄存器组的首地址,其成员与寄存器组中的寄存器一一对应比如访问输出数据寄存器,可以这样GPIOA->ODR。 形成一个映射关系(类型转换,寄存器地址转成结构体成员),访问成员就是访问寄存器。 一个引脚需要四位来配置(CNFy[1:0]与MODEy[1:0]): 端口(引脚):一个引脚需要四位来配置,16个引脚是需要16*4=64,我们单片机它是32位的,所以说它的寄存器是32位的,你需要两个寄存器来进行配置。 因此需要高低配置寄存器,高8位端口,低8位端口。 宏定义左移右移。 低八位; PA0是0000,如果要想配置其他几位,如PA2,你只需要把0001就左移8(2*4)位。如PA3,0001就左移12(3*4)位. 高八位:(端口配置高寄存器 端口配置高寄存器(GPIOx_CRH) ) 如果要想配置其他几位,如PA14,只需要左移8((14-8)*4=24)位。 端口输入数据寄存器(GPIOx_IDR)你把工作模式配置成输入,只需要把这里面的数据读出来,就可以知道单片机引脚中的数据了。 PA0数据:IDR0 PA1数据:IDR1 端口输出数据寄存器(GPIOx_ODR)要输出什么电平,就往这个数据寄存器对应的位写01 比如说现在是是GPIOA,只要往这一位( ODR10)写1,表示PA10输出高电平。 ( ODR8)写1,表示PA8输出高电平。( ODR8)写0,表示PA8输出低电平。 端口位设置/ 清除寄存器(GPIOx_BSRR)BS,16位是控制高电平输出:只要写1就是高电平 BR,16位是控制低电平输出:只要写1就是低电平 注:如果同时设置了BSy和BRy的对应位,BSy位起作用 端口位清除寄存器(GPIOx_BRR)1:清除对应的ODRy位为0 同上BR功能,只要写1就是低电平。 往BR13写1,PA9就低电平。 注意: 端口位设置/ 清除寄存器(GPIOx_BSRR)和端口位清除寄存器(GPIOx_BRR) 都是间接操作端口输出数据寄存器(GPIOx_ODR)。 一般直接操作输出数据寄存器(GPIOx_ODR) 常用的就四个寄存器:端口配置低寄存器(GPIOx_CRL),端口配置高寄存器(GPIOx_CRH),端口输入数据寄存器(GPIOx_IDR),端口输出数据寄存器(GPIOx_ODR) 明白如何输出01和读取单片机引脚的电平。 外部中断:通过单片机引脚进行的,一种输入,可以产生中断。 第4-4节:点亮LED_寄存器版本 代码逻辑框图1.宏定义8种模式 GPIO.h #ifndef __GPIO_H #define __GPIO_H //上拉下拉都是0X08,由ODR寄存器区分。ODR:0下拉,1上拉。 #define GPIO_INPUT_ANALOG 0X00 #define GPIO_INPUT_NOPULL 0X04 #define GPIO_INPUT_PULLUP 0X08 #define GPIO_INPUT_PULLDOWN 0X08 #define GPIO_OUTPUT_PP 0X00 #define GPIO_OUTPUT_OD 0X04 #define GPIO_OUTPUT_AF_PP 0X08 #define GPIO_OUTPUT_AF_OD 0X0C #define GPIO_SPEED_10MHZ 0X01 #define GPIO_SPEED_2MHZ 0X02 #define GPIO_SPEED_50MHZ 0X03 #endifLED初始化函数 第一步还是打开时钟 RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;紧接着进行配置(配置寄存器两个,高八位、低八位) 我使用的GPIOA4是低八位。 推挽+2MHZ,GPIOA4 = 4*4 = 16 左移16位 GPIOA->CRL |= (GPIO_OUTPUT_PP + GPIO_SPEED_2MHZ)CRL |= (GPIO_OUTPUT_PP + GPIO_SPEED_2MHZ)ODR |= 1CRH &= ~(0XFFFF0FFF); //正确写法,与0直接就行,不是用1 第5-1节:STM32按键检测算法单片机它可以控制外部的设备,还可以读取外部设备的状态。如:按键是否被按下。如何判断呢? 单片机它只能输入模拟信号,还有就是输入高低电平这种数字信号 按键它其实是一个开关,按下去跟没按下去两种转态(读取数字信号),这种数字信号如何读呢?单片机它是可以直接读数据数字信号的,只需要根据这个引脚的高低电平,就可以判断出按键是否被按下。 归根结底就是判断高电平和低电平 编程:一般可以用if语句来判断。 不使用长时间延迟,改而在多次判断,防止抖动误判。 代码逻辑框图:1. 2. 3. 4. 5. 输入:模拟,浮空,上下拉 输出: PP,OD,AFPP,AFOD 寄存器里面上下拉的设置,由数据寄存器GOID->ODR决定,数据寄存器对应的位为1,就是上拉,因为你输出高电平嘛,上拉才会是高电平。下拉,数据寄存器必须输出零。 上拉: GOID->ODR |= 1CRL |= (GPIO_INPUT_PULLUP) |
CopyRight 2018-2019 实验室设备网 版权所有 |