国内做市场调查专业网站,网站关键词怎样做优化,it运维,软件外包公司招聘目录 1.1. 预备阶段
1.2. 单片机介绍
2. 初识STM32
2.1. STM32 1.1. 预备阶段
1.2. 单片机介绍
1.2.1. 单片机是什么
单片微型计算机(Single Chip Microcomputer)简称为单片机#xff08;Microcontrollers#xff09;#xff0c;也称为微控制单元(Microcontroller Uni…目录 1.1. 预备阶段
1.2. 单片机介绍
2. 初识STM32
2.1. STM32 1.1. 预备阶段
1.2. 单片机介绍
1.2.1. 单片机是什么
单片微型计算机(Single Chip Microcomputer)简称为单片机Microcontrollers也称为微控制单元(Microcontroller UnitMCU) 也就是嵌入式微控制器。单片机是采用集成电路技术将中央处理器CPU、随机存取存储器RAM(Random Access Memory)、只读存储器ROM(Read-Only Memory)、Flash、多路IO、定时器、计数器、中断系统等设备集成到一块微型硅片上。 可以将单片机看做一个小型且完善的计算机系统。
1.1.3. 应用场景及就业方向
1.1.3.1. 智能设备 单片机工程师 嵌入式工程师
2. 初识STM32
2.1. STM32
2.1.1. 什么是STM32
2.1.2. STM32产品介绍 2.1.3. STM32产品命名规范 2.1.4. STM32与M3的关系
2.1.5. M3与ARM
2.1.6. STM32F0系统架构 系统主要由以下几个模块组成:
两个主模块
·Cortex-M0 内核及先进高性能总线(AHB bus)
·通用 DMA ( GP-DMA -- general-purpose DMA)
四个从模块
·内部 FLASH
·内部SRAM
·专门用于连接 GPIO 口的 AHB2
·AHB 到 APB 的桥 , 所有的外设都挂在 APB 总线上
2.2. 开发平台介绍
2.1. 使用的什么芯片
STM32F051K8U6
STM32F051
ARM Cortex-M0、32位低功耗微处理器、48 MHz 工作频率、64 Kbytes Flash、8 Kbytes SRAM、32 pin STM32G030C8T6
2.2. NB-IoT硬件平台介绍-开发板 LCD的屏用的是spi协议平时的大多数的摄像头也是spi协议。
一键还原卡接口就是防止WiFi芯片程序出问题的这里把图上的NB-IoT换成了WiFi芯片
在线仿真和烧写看着这么多引脚其实烧写时起作用的就4个电源、GND、两个数据传输的。
2.3. 设备各个组成部分
传感器介绍
传感器英文名称transducer/sensor是一种检测装置能感受到被测量的信息并能将感受到的信息按一定规律变换成为电信号或其他所需形式的信息输出以满足信息的传输、处理、存储、显示、记录和控制等要求。
无人机中的传感器
加速度计
加速度计是用来提供无人机在XYZ三轴方向所承受的加速力。它也能决定无人机在静止状态时的倾斜角度。 当无人机呈现水平静止状态X轴与Y轴为0G输出而Z轴则为1G输出。 地球上所有对象所承受的重力均为1G。若要无人机X轴旋转90度那么就在X轴与Z轴施以0G输出Y轴则施以1G输出。倾斜时XYZ轴均施以0到1G之间的输出。相关数值便可应用于三角公式让无人机达到特定倾斜角度。
陀螺仪
陀螺仪传感器能监测三轴的角速度因此可监测出俯仰(pitch)、翻滚(roll)和偏摆(yaw)时角度的变化率。即使是一般飞行器陀螺仪都是相当重要的传感器。角度信息的变化能用来维持无人机稳定并防止晃动。由陀螺仪所提供的信息将汇入马达控制驱动器通过动态控制马达速度并提供马达稳定度。 陀螺仪还能确保无人机根据用户控制装置所设定的角度旋转。
磁罗盘
磁罗盘能为无人机提供方向感。它能提供装置在XYZ各轴向所承受磁场的数据。接着相关数据会汇入微控制器的运算法以提供磁北极相关的航向角然后就能用这些信息来侦测地理方位。
气压计
气压计运作的原理就是利用大气压力换算出高度。 压力传感器能侦测地球的大气压力。 由气压计所提供的数据能协助无人机导航上升到所需的高度。准确估计上升与下降速度对无人机飞行控制来说相当重要。
超声波传感器
无人机采用超声波传感器就是利用超声波碰到其他物质会反弹这一特性进行高度控制。前面就提到过近地面的时候利用气压传感器是无法应对的。但是利用超声波传感器在近地面就能够实现高度控制。这样一来气压传感器同超声波传感器一结合就可以实现无人机无论是在高空还是低空都能够平稳飞行。
GPS
GPS是全球导航系统之一是美国的卫星导航系统。不过最近的无人机开始不单单采用GPS了有些机型会同时利用GPS与其他的卫星导航系统相结合同时接收多种信号检测无人机位置。无论是设定经度纬度进行自动飞行还是保持定位进行悬停GPS都是极其重要的一大功能。
麦克风\温湿度
湿度传感器能监测湿度参数相关数据则可应用在气象站、凝结高度监测、空气密度监测与气体传感器测量结果的修正
麦克风是一种能将声音频号转换为电子讯号的音频传感器
WIFI\蓝牙
无人机有各种不同的联网技术选项可考虑。 低功耗蓝牙(BLE)与Wi-Fi多半用于智能手机联网Sub-1GHz则是用在远程控制器能提供更远距离的联网功能。
1.2.3. 如何开发
1.2.3.1. 电脑 PC
1.2.3.2. STLINK JLINK
1.2.3.3. 设备
1.2.3.4. 串口调试
1.2.3.5. KEIL MDK
1.2.3.6. STM32CUBEMX
3. 开发环境搭建
3.1. STM32CubeMX安装
3.1.1. 简介
微控制器图形化配置 自动处理引脚冲突 动态设置确定的时钟树 可以动态确定参数设置的外围和中间件模式和初始化
功耗预测
C代码工程生成器覆盖了STM32微控制器初始化编译软件如IARKEILGCC可以独立使用
3.2. HAL库与STD库
1、STD库-标准外设库
寄存器操作将一些基本的寄存器操作封装成函数
标准库这里会提供一个底层包用这个包直接调它的API就行。
2、 HAL库-硬件抽象库
Hardware Abstraction Layer (HAL)硬件抽象层
将这些抽象成了一个抽象层从使用的角度来看是与硬件无关的
HAL库就是他原本没有这些支持包现在用HAL给你生成一个支持包通过图形化的配置将一些基本的比如GPIO口
3、HAL库优势
HAL库是ST未来主推的库从2015开始ST新出的芯片已经没有STD库
HAL库的处理机制比STD库好很多HAL库支持STM32全线产品
HAL库跨芯片的可移植性非常好
3.3. HAL库与STD库区别
1.HAL库就是封装的比较猛移植性比较强标准库就是将寄存器封装好移植性没有HAL好。
2.HAL库可以用ST的软件CUBE生成初始化工程。3.HAL库最方便的就是可以用CUBEMX自动生成代码动态的调用资源不会出现地城配置上的冲突。
4.其实就是两种库的区别Hal库更加全面一点目前STM32官方也在主推Hal库目前STMcubemx软件可以直接生成HAL库代码非常方便编程易移植。
5.HAL库是ST近年来推出的新库可以直接在CubeMX下生成例程并且各个不同型号的STM32之间的函数差异也减少了。
6.HAL库是现在ST主推的库标准库现在已经不更新了。HAL库做了更深的封装可以很方便的移植在F0/F1/F3/F4/F7的各个系列的芯片上。
7.hal库通用型强但是效率稍微低一点标准库效率高。
8.本质上是一样的就是配置寄存器只是HAL库将应用层与驱动层分的比较明确。
9.HAL库设计进一步降低了API对硬件的依赖性它借鉴了OS中驱动程序的思路使得API的通用性更强。 能使用ST的CubeMX图形化界面来生成软件框架它和CubeMX生成的软件代码完全兼容。减少了程序员的负担同时代码也更规范。 至于与原库函数之间的使用差异 关键还是要掌握内核及外设的工作原理如果熟悉了硬件的工作原理这些库函数还是很好用的。
10.HAL库似乎是为初学者而制定但这也许是STM32的未来所在。
11.HAL和STD库最大的区别是移植性上的区别HAL相当于在标准库上在加以封装了。增强了移植性STD库是在寄存器的基础上封装了一次。12.hal库封装的更想arduino移植性强相对效率就低一些在时间就是金钱的现在hal库无疑是很好的选择。
13.HAL库和标准库都是对寄存器操作的封装但是这些库的函数不同在HAL库每个.c文件的开头会介绍这个库里面包含哪些函数这些函数的用途可以留意一下。
14.标准库是STM32最早推出的库应用非常广泛但是比较新的F7和H7等系列已经不支持了。
HAL库是官方主推的库目前支持所有系列相对效率没有标准库高但是各个系列之间的兼容性很好而且能够配合STM32CubeMX进行使用。由于官方现在不在更新和支持标准库了所有精力都放在了HAL库和LL库上了所以建议今后学习和应用还是以HAL库和LL库为主要对象。
15.hal库和标准库的最大区别就是减少了不同系列器件之间的库函数层差异并且可以直接用cubemx生成。
16.HAL移植性比较强可以通过cubemx生成代码不过效率比较低标准库更像寄存器的操作感觉更符合对寄存器使用的理解。
17.HAL库移植性比较好操作比较简单。标准库移植性没那么方便操作比较复杂直接对寄存器的操作。
18.HAL库的封装比较多大部分都是面向对象的设计移植比较简单。
19.HAL的优点就是用API的设计十分方便移植而且操作也简单。
20.HAL的移植性是最好的但是标准库不太方便移植所以ST出了一个HAL库。 4. GPIO编程
4.1. GPIO的基本概念及寄存器介绍
GPIO接口简介
通用输入输出接口GPIO是嵌入式系统、单片机开发过程中最常用的接口用户可以通过编程灵活的对接口进行控制实现对电路板上LED、数码管、按键等常用设备控制驱动也可以作为串口的数据收发管脚或AD的接口等复用功能使用。因此其作用和功能是非常重要的。
GPIO功能复用
STM32有很多的内置外设这些外设的外部引脚都是与 GPIO 复用的。也就是说一个 GPIO如果可以复用为内置外设的功能引脚那么当这个 GPIO 作为内置外设使用的时候就叫做复用。
GPIO寄存器介绍
什么是寄存器
寄存器的功能是存储二进制代码它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码故存放n位二进制代码的寄存器需用n个触发器来构成
GPIO寄存器
4个32位配置寄存器
GPIOx_MODER
GPIOx_OTYPER
GPIOx_OSPEEDR
GPIOx_PUPDR
2个32位数据寄存器
GPIOx_IDR 、GPIOx_ODR
GPIOx_ODR 1 个32 位置位 / 复位寄存器
GPIOx_BSRR 可以用这个寄存器来写灯
只把相应的位置位复位就可以了 GPIO_PIN_SET高电平此时灯关低电平的时候灯开
只需要把对应的位置0就可以实现低电平然后控制灯开 这样就把蓝黄绿灯点亮了。 2 个 32 位复用功能配置寄存器
GPIOx_AFRH 、GPIOx_AFRL 1.4.2. 点亮LED
模式配置
输入模式有4种浮空输入、上拉输入、下拉输入、模拟输入。
浮空输入可读取引脚电平引脚悬空不确定输入的电平。
上拉输入可读取引脚电平内部默认接上拉电阻即默认输入高电平。
下拉输入可读取引脚电平内部默认接下拉电阻即默认输入低电平。
模拟输入引脚直接连接片上AD模块把外部模拟信号做AD转换时接入引脚设置为模拟输入模式。
输出模式有4种推挽输出、开漏输出、复用推挽输出、复用开漏输出。
推挽输出可认为是有输出高电平能力的输出IO口具有输出高电平的能力。
开漏输出需连接上拉电阻才可输出高电平。
复用推挽输出类似推挽输出区别是输出由片上外设而非IO口寄存器定义比如SPI、IIC等外设
复用开漏输出类似开漏输出区别是输出由片上外设而非IO口寄存器定义比如SPI、IIC等外设 Analog模拟
图详见《 STM32F0数据手册》118页 施密特触发器作用是判断高低电平起到一个比较的作用当你输入一个高于它一个比较电压的时候比如单片机是输入一个高于0.7的就算高电平低于0.3的就算低电平。这时就会有一个0.3到0.7之间的差距有时候写程序有问题的时候可能是卡在这个区间里它识别不到大概是这个区域有误差。 复位就是从1变成0
置位就是设置成1
GPIO寄存器 输出控制
按键: (PA8配置成GPIO_input) (配置成GPIO模式等信息) 下拉设置因为按键端按下是高电平所以我们配置成下拉这样默认情况下是低可以更稳定) 读取按键电平信息 HAL_RCC_GPIOA_CLK_ENABLE 使能用的如果不是A需要换下 HAL_GPIO_Togglepin 输出时的高低电平翻转函数 翻转函数内部 效果就是按一下亮再按一下灭这样循环。
按键流水灯使用switch来做
switch复习 代码 while (1)
{/* USER CODE END WHILE *//* USER CODE BEGIN 3 */switch (num){case 0:if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8)){HAL_Delay(100);HAL_GPIO_WritePin(GPIOB, GREEN_Pin, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, BLUE_Pin, GPIO_PIN_RESET);while (!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8)){num;break;}}break;case 1:if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8)){HAL_Delay(100);HAL_GPIO_WritePin(GPIOB, BLUE_Pin, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, YELLOW_Pin, GPIO_PIN_RESET);while (!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8)){num;break;}}break;case 2:if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8)){HAL_Delay(100);HAL_GPIO_WritePin(GPIOB, YELLOW_Pin, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GREEN_Pin, GPIO_PIN_RESET);while (!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8)){num;break;} while (1)
{if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8)){HAL_Delay(200);while ((HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8))){};num;switch (num){case 1:HAL_GPIO_WritePin(GPIOB, BLUE_Pin, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, GREEN_Pin, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, YELLOW_Pin, GPIO_PIN_SET);break;case 2:HAL_GPIO_WritePin(GPIOB, YELLOW_Pin, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, BLUE_Pin, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, GREEN_Pin, GPIO_PIN_SET);break;case 3:HAL_GPIO_WritePin(GPIOB, GREEN_Pin, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOB, YELLOW_Pin, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOB, BLUE_Pin, GPIO_PIN_SET);break;default:num 0;break;}}
}
5. 通信的基本概念
串口通信
通信最少要有两个对象一个收一个发
同步通信 一般情况下同步通信指的是通信双方根据同步信号进行通信的方式。比如通信双方有一个共同的时钟信号大家根据时钟信号的变化进行通信 异步通信
是指数据传输速度匹配依赖于通信双方有自己独立的系统时钟大家约定好通信的速度。异步通信不需要同步信号但是并不是说通信的过程不同 串行通信 并行通信 串行通信指的是同一时刻只能收或发一个bit位信息。因此只用1根信号线即可。 并行通信指的是同一时刻可以收或发多个bit位的信息因此需要多根信号线才行 -串行传输数据按位顺序传输。 -优点占用引脚资源少 -缺点速度相对较慢 -并行传输数据各个位同时传输。 -优点速度快 -缺点占用引脚资源多
全双工 半双工 单工 单工要么收要么发只能做接收设备或者发送设备。比如收音机 半双工可以收可以发但是不能同时收发 比如对讲机 全双工可以在同一时刻既接收又发送 手机 常见通信总结 USART介绍 概念介绍 通用异步收发器UART灵活地与外部设备进行全双工数据通信满足外部设备对工业标准NRZ异步串行数据格式的要求。USART通过小数波特率发生器提供了多种波特率。它支持同步单向通信和半双工单线通信还支持LIN局域互联网络智能卡协议与IrDA红外数据协会SIR ENDEC规范以及调制解调操作CTS/RTS。而且它还支持多处理器通信。 USART支持同步模式因此USART 需要同步始终信号USART_CK如STM32 单片机通常情况同步信号很少使用因此USART和一般单片机UART使用方式是一样的都使用异步模式。 这里这个CH340是串口的USB转TTL信号的。
STM32F051串口 串口电路连接 串口通信协议介绍 波特率
在串行通信中用“波特率”来描述数据的传输速率。所谓波特率既每秒传送的二进制位数其单位为bpsbits per second。它是衡量串行数据速度快慢的重要指标。
国际上规定一个标准的波特率系列 110、300、600、1200、1800、2400、4800、9600、115200、14.4Kbps、19.2Kbps、……
例如115200bps、指每秒传送115200位。通信双方必须设置同样的同学速率才能正常通信
注意实际的数据没这么多还包括起始位结束位校验位 选择串口功能 配置成异步通信Asynchronous USART寄存器介绍 控制寄存器——USART_CR 状态寄存器——USART_SR 数据寄存器——USART_DR 波特率寄存器——USART_BRR不要纠结这个计算比较难直接用函数就可以 STM32实现串口数据的收发
串口的发送函数:
HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) 函数内部有用到寄存器 用一下这个函数 打开串口调试助手按一下复位键就会有发送的消息 串口的接收:
HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) 函数内部有RDR 串口寄存器
控制寄存器CR1、CR2 波特率寄存器BRR 中断和状态寄存器ISR 数据发送寄存器TDR 数据接收寄存器RDR printf重定向 printf函数调用的是c库中的fputc函数。因此我们如果重新写了fputc函数就可以改变printf函数的功能可以向串口打印输出。
int fputc(int ch, FILE *f) //重定向函数
{while (!(USART1-ISR (1 7)));USART1-TDR ch;return ch;
}
int rdrc() //寄存器方式接收一个字节
{int ch;while (!(USART1-ISR (1 5)));ch USART1-RDR;return ch;
}
void gettc(int ch) //寄存器方式发送一个字节
{while (!(USART1-ISR (1 7)));USART1-TDR ch;
} 写一下程序 烧录了之后按复位打开串口调试助手就会看到一直在打印 然后可以改一下直接用这个函数发送一个字符 烧录复位后打开串口调试助手可以看到一直在发一个字符c 数据只管写到TDR然后移位寄存器再将数据移出然后发送
就是这个移位寄存器程序里不用管它硬件上直接就往外移了就是在搬砖有砖就搬有砖就搬 再写一个接收的程序 下面改成接收的这个函数 然后烧录复位打开串口调试助手可以看到点一下发送就会回复 6. STM32中断系统
中断的基本概念
处理器中的中断
在处理器中中断是一个过程即CPU在正常执行程序的过程中遇到外部/内部的紧急事件需要处理暂时中止当前程序的执行转而去为处理紧急的事件待处理完毕后再返回被打断的程序处继续往下执行。中断在计算机多任务处理尤其是即时系统中尤为重要。比如uCOSFreeRTOS等。
意义
中断能提高CPU的效率同时能对突发事件做出实时处理。实现程序的并行化实现嵌入式系统进程之间的切换
中断处理过程 STM32F0中断的体系结构
下面这个图需要了解一下他们大概的位置关系 中断和异常向量表
STM32F0中断和异常向量
Cortex-M0内核可以处理15个内部异常和32个外部中断。
STM32F051实际上只使用了6个内部异常和28个外部中断。
当异常或中断发生时处理器会把PC设置为一个特定地址这一地址就称为异常向量。每一类异常源都对应一个特定的入口地址这些地址按照优先级排列以后就组成一张异常向量表。 向量化处理中断的好处
传统的处理方式需要软件去完成。采用向量表处理异常M0处理器会从存储器的向量表中自动定位异常的程序入口。从发生异常到异常的处理中间的时间被缩减。 中断和异常向量表 注中断和异常的区别 中断是微处理器外部发送的通过中断通道送入处理器内部一般是硬件引起的比如串口接收中断而异常通常是微处理器内部发生的大多是软件引起的比如除法出错异常特权调用异常等待。不管是中断还是异常微处理器通常都有相应的中断/异常服务程序 外部中断控制器EXTI
在 STM32F05x 中共有最多 28 中断 / 事件线可用
GPIO 口连接到 16 个外部中断 / 事件线 系统配置控制器 (SYSCFG) SYSCFG 外部中断配置寄存器 1-4 (SYSCFG_EXTICR1—4) 外部中断 / 事件框图 按键中断 配置步骤 这里能找到 还可以这样 复制 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
放到gpio.c里找个位置放 但一定要放到BEGIN和END中间就是防止再生成程序的时候给生成没了 向量表 GPIO模式配置 还有一个问题
按键中断了还需要削抖吗
不需要。因为是上升沿或者是下降沿触发直上直下没有抖动这个问题了。抖动是因为手碰或者一些机械元件接触机械元件接触的时候它是不稳定的。 串口中断
串口中断分为接收中断和发送中断。
之前这个图 串口有一个直接可以到NVIC的一个中断所以串口也是可以用中断来识别的就是接收过来信号有接收中断发送过来的有发送中断这两个。
打开CubeMX对串口的发送中断进行配置 右键跳转 如果上面下划找不到还可以 找到要用的复制到usart.c 然后找到这个 usart.c main.c: 另一个程序 复制了放到usart.c里边为什么放这里边归类一下 烧录打开串口调试助手就可以看到 再来分析一下 串口发送完成中断
实验分析网络指示灯正常1s闪烁串口发送指定的字符个数当发生完成时切换发送指示灯状态并打印“发送完成”。
实验步骤
1配置CubeMX
USART1 - 异步 - 115200bps
PB1 - GPIO_OUTPUT - HIGH
PB0 - GPIO_OUTPUT - HIGH
NVIC - 使能USART1 global interrupt
2代码编写
在main.c实现网络指示灯闪烁
while (1)
{HAL_GPIO_TogglePin(GREE_GPIO_Port, GREE_Pin);HAL_Delay(1000);
} 在uart.c实现中断服务程序
先找到发送完成的中断回调函数
打开启动代码start.s
107行 DCD USART1_IRQHandler ; USART1
void USART1_IRQHandler(void)
{HAL_UART_IRQHandler(huart1);
} 调用了串口中断服务程序将串口1的句柄作为参数进行传递。 在HAL_UART_IRQHandler的2577行
/ UART in mode Transmitter (transmission end) -----------------------------/
if (((isrflags USART_ISR_TC) ! 0U) ((cr1its USART_CR1_TCIE) ! 0U))
{UART_EndTransmit_IT(huart);return;
} 串口发送结束中断
static void UART_EndTransmit_IT(UART_HandleTypeDef *huart)
{ATOMIC_CLEAR_BIT(huart-Instance-CR1, USART_CR1_TCIE);huart-gState HAL_UART_STATE_READY;huart-TxISR NULL;#if (USE_HAL_UART_REGISTER_CALLBACKS 1)huart-TxCpltCallback(huart);#elseHAL_UART_TxCpltCallback(huart);#endif
} 找到串口发送完成中断回调函数 HAL_UART_TxCpltCallback(huart);
__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{UNUSED(huart);
} 在uart.c重写HAL_UART_TxCpltCallback
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{if(huart-Instance USART1){HAL_UART_Transmit(huart1,Transmit complete!,sizeof(Transmit complete!), HAL_GPIO_TogglePin(BLUE_GPIO_Port,BLUE_Pin);}
} 回到main.c
HAL_StatusTypeDef HAL_UART_Transmit_IT (UART_HandleTypeDef huart, uint8_t pData, uint16_t Size)
参数UART_HandleTypeDef * huart 句柄uint8_t * pData 发送数据的首地址uint16_t Size 发送数据的长度
HAL_UART_Transmit_IT(huart1,hello\n,strlen(hello\n));
//发送“hello”发送完成后调用发送完成中断回调函数打印Transmit complete!。
通过串口一次发送多个字符 代码
/* USER CODE BEGIN 0 */
void uart_putchar(uint8_t ch)
{while(!(USART1-ISR (17))); //while等待发送寄存器为空ISR第七位为1说明发送寄存器为空则应该跳出循环向下执行。USART1-TDR ch;
}
//通过串口接收字符函数
uint8_t uart_getchar()
{uint8_t ch;while(!(USART1-ISR (15))); //等待接收数据寄存器非空ISR的第五位为1说明接收寄存器里接收到了数据。ch USART1-RDR;return ch;
}
//通过串口发送字符串函数
void uart_puts(uint8_t *s)
{while(*s){uart_putchar(*s);s;}
}
//通过串口接收字符串函数
void uart_gets(uint8_t *s)
{while(1){*s uart_getchar();if(*s ||*s \n) // 字符串通常以空格和反斜杠n结尾{break;}s;}
}
/* USER CODE END 0 */ main.c 外层 烧录复位后打开串口调试助手 7. STM32时钟系统
1.时钟的概念
1时钟是嵌入式系统中的脉搏处理器内核是时钟的驱动下完成指令执行、状态切换等动作的。
外部设备在时钟驱动下完成各项工作。比如串口通信、AD转换、定时器计数...
因此时钟对我们计算机系统来说至关重要通常来说时钟出现问题一般都是致命性问题。
2时钟系统由时钟源振荡器、定时唤醒器、分频器、倍频器等组成的电路。
常用的信号源有
RC振荡器
优点成本低由电阻电容构成。启动时间短。
缺点精确度存在问题不够稳定容易受到环境因素影响。
晶体振荡器
优点时钟信号更加稳定、精度高
缺点价格高、需要较长的起振时间。 倍频器CPU需要较高的频率制作高频振荡器成本较高就可以利用倍频器对现有的时钟频率进行倍频来供给CPU。
分频器外部设备需要不同的时钟频率进行工作可以通过分频器产生不同的时钟频率供给各个外设。
面试题为什么要有倍频器和分频器
答 1为了降低成本CPU需要更高的时钟频率 2减少功耗 外设需要不同的时钟频率
2.STM32有四个时钟源
HSI:高速内部时钟RC振荡器频率为8MHz
HSE:高速外部时钟可接石英/陶瓷谐振器4到32 MHz外部振荡器可为系统提供非常精确的主时钟。
LSI:低速内部时钟RC振荡器频率为40KHz。它可以在停机和待机模式下保持运行为独立看门狗和 RTC 提供时钟
LSE:低速外部时钟接32.768KHz的石英晶体。它为实时时钟或者其他定时功能 提供一个低功耗且精确的时钟源
PLL:锁相环倍频输出它的时钟输入源也是HSE或HSI经过分频得到的。
有时候会说5个但是从源头上来说还是4个因为PLL是经过分频得到的。
STM32Cubemx配置时钟 HAL_Delay()分析1 SysTick定时器工作原理图 3.时钟复位控制 RCCreset clock controller
RCC 通过 AHB 时钟 (HCLK)8 分频后作为 Cortex 系统定时器 (SysTick) 的外部时钟。
通过对 SysTick 控制与状态寄存器的设置可选择上述时钟或 Cortex(HCLK) 时钟作为 SysTick 时钟。
中文参考手册84页 图10 时钟树 重点看 SysTick 滴答定时器
概念
能够用于定时、计数的器件称为定时器。
systick是在Cortex-M0内核内部的跟NVIC捆绑在一起的产生systick异常用于对输入的时钟进行计数。
工作原理
滴答定时器本质上就是一个24位递减计数器也就是最大计数是2^24 - 10xFFFFFF
在给Systick设定初值后每当到来一个时钟信号计数值则减1直到计数值减到0时
触发一次异常事件处理异常服务程序处理完成后计数器再自动重装初值并继续减一依次循环。 HAL_Delay()分析2 SysTick寄存器 比如说重装载值是100当前值是0当前值就是这个减数过程中值的数字我们如果想要让它更精确就把它在延时的时候先把它放在初始值这里让它从0开始装回去从100再减这样就保障了延时的准确性怎么达到100us呢就是100一直减减到0然后又重新回来100。
知道频率怎么算周期呢
周期就是频率的倒数
48MHz的用1us要记48个数
所以把重装载值寄存器LOAD记48 1微秒是48多少微秒就乘以多少就得到了我们想要得到的延时数。 然后去中文参考手册去找时钟
AHB外部时钟使能寄存器(RCC_AHBENR) 然后发现第18位是GPIOB的 我们用一个东西首先得开启它的时钟 复制后进到gpio.c中放在GPIO初始化函数void MX_GPIO_Init(void)中然后把下划线改成- 然后把第18位置1使能一下 然后对GPIO口进行配置首先有一个输入输出的配置咱们这是输出输出有一个速度还有一个是开漏还是推挽主要是这些上拉下拉可以配置也可以不配置。
然后就去找GPIO的寄存器
GPIO 端口模式寄存器 (GPIOx_MODER) (x A..D,F) 寄存器分析 同样复制寄存器的名字GPIOx_MODER然后把下划线改成- 然后看速度 GPIO 口输出速度寄存器 (GPIOx_OSPEEDR) (x A..D,F) 然后把速度这个置0一下 GPIO_PIN_0的在第0位置0GPIO_PIN_1的在第2位置0GPIO_PIN_2在第4位置0。
然后配置输出类型
GPIO 端口输出类型寄存器 (GPIOx_OTYPER) (x A..D,F) GPIO_PIN_0的在第0位置0设置推挽输出 GPIO_PIN_1在第1位置0 GPIO_PIN_2在第2位置0 然后我们想给它一个默认的电平默认让它灭 其他两个灯也同理 下面看一下比如直接写GPIO_PIN_0是怎么样的原理 写好了之后去到main函数里
低电平亮的话指向BRR也行 端口位复位寄存器 (GPIOx_BRR) (xA..G) STM32TIM定时器
功能 三种定时器区别 计数模式
通用定时器可以向上计数、向下计数、向上向下双向计数模式。
①向上计数模式计数器从0计数到自动加载值(TIMx_ARR)然后重新从0开始计数并且产生一个计数器溢出事件。
②向下计数模式计数器从自动装入的值(TIMx_ARR)开始向下计数到0然后从自动装入的值重新开始并产生一个计数器向下溢出事件。
③中央对齐模式向上/向下计数计数器从0开始计数到自动装入的值-1产生一个计数器溢出事件然后向下计数到1并且产生一个计数器溢出事件然后再从0开始重新计数。 合并图 中心对齐就是到中间就已经重新装了相当于走一个向上计数的也走一个向下计数的。
寄存器 这儿有个计数器相当于当前值什么的对数据进行计数的 配置
选第二个
时钟源-内部时钟 这里配置的是48MHz 这里48减1是1us如果配置72MHz的就写72-1也是1us效果一样的 如果想用1s的话就填0,1加上六个0 然后继续配置 生成工程后在.s文件里可以跳转 F051的在3949行 复制之后去tim.c里找个地方 记得在tim.c里加头文件 在主函数中要开启一下 分析一下 有了这个公式就能计算延时时间
例如 还有 寄存器 软件定时器应用
利用软件定时器实现LED1s闪烁 直接去文件夹下新建一个.h 代码 main函数里 烧录后实际的效果就是蓝黄绿间隔1s闪烁。 记录
系统定时器先获取一个当前值就是程序从上电或者复位开始存上这个当前值后就开始一直获取这个最新的和那个存储的当前值相减 自己写的软件定时器
先把当前时间获取到用HAL_GetTick()获取需要再有一个定时的时间定时的时间是自己设置的以毫秒为单位比如想定500ms就传一个参数500就好用结构体封装这两个变量当前值获取到就固定了和传的定时时间然后把刚才的参数转换一下子转换就是再写一个类似系统写的延时器比如先命名一个结构体MyTim然后不断的获取最新的时间最新的时间获取了之后减去上边那个一开始的当前时间这样就得出一个时间差就是你运行了多久只要大于等于那个延时时间就说明这个时间到了就return个1没到就return个0习惯性正确的是1不正确的是0然后就判断这个返回的数值是1还是0。
这个就是在while里轮询着面试时候问你这个是什么算法就说轮询 pwm需要用到的东西
电阻是干什么的限流、分压
电容 滤波按键有抖动加电容就把抖动时间弄过去了
数码管什么原理ABCDEFG加一个点.八段每一个都是二极管
共阴就是公共接的都是阴共阳就是接的阳
蜂鸣器分两种有源和无源
无源就是里面有个小铜铝片两边连出来直接输高低电平是不会响的需要一边一直哆嗦。
有源的就类似咱们时钟 【1】定时器 STM32F0系列器件包含6个通用定时器、1个基本定时器、1个高级定时器 a.通用定时器TIM2 3 14 15 16 17功能 ● 定时器定时定时器计数 ● 输入捕获 ● 输出比较 - 输出PWM b.高级定时器TIM1功能 ● 通用定时器的有功能 ● 带死区控制和紧急刹车可用于PWM控制电机【*】 c.基本定时器TIM6功能 ● 主要运用于定时计数以及驱动DAC 定时器计数模式
向上计数模式计数器从0开始计数当达到自动装载寄存器(TIMx_ARR)里的值时自动清零且产生一个溢出事件然后再从0开始向上计数。。
向下计数模式计数器从自动装载寄存器(TIMx_ARR)里的值开始递减计数当计数值达到0时产生一个定时器溢出事件并重装初值继续向下计数。
中央对齐模式又称为向上/向下计数计数器从0开始递增达到ARR的值产生一个定时器溢出事件再从ARR的值递减到0产生一个定时器溢出事件。 定时器计数原理
时钟频率配置成了48Mhz如何让定时器产生1s中断
分频值写0相当于不分频 48/1 48
先对主频进行48分频得到1Mhz的频率则分频值为48-1 48Mhz / 48 1Mhz 1Mhz的时钟频率相当于计一个数需要1/1000000秒 所以如果想得到1s中断则需要从0开始计数到1000000-1即计1000000个数需要1秒。
1000000个数 * 1/1000000s 1s
频率是时间的倒数 1Mhz 1/1000000s 实验一定时器定时打印
实验分析利用定时器实现1秒中断在定时器的中断服务程序中打印“helloworld”
实验步骤
配置CubeMX
1设定时钟频率为48M
RCC - 晶体/陶瓷谐振器 - 主频48Mhz
2可以使能高速外部时钟 - RCC - Crystal/Ceramic Resonator晶体/陶瓷谐振器 - OSC-IN OSC-OUT
使能串口USART1 - 异步通信ASY - 115200bps
3配置通用定时器TIM2 TIM2 - 时钟源 - 内部时钟 - APB - 48Mhz 分频值 - 48分频 - 48 - 1 计数模式 - 向上计数 自动重载计数器 - 1000000 - 1
编写代码
找到中断服务程序的入口地址
DCD TIM2_IRQHandler ; TIM2
TIM2的中断服务程序
void TIM2_IRQHandler(void)
{HAL_TIM_IRQHandler(htim2);//定时器中断服务程序
} 进入HAL_TIM_IRQHandler
在3940行 定时器计数事件
/* TIM Update event */
if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) ! RESET)
{if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) ! RESET){__HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
#if (USE_HAL_TIM_REGISTER_CALLBACKS 1)htim-PeriodElapsedCallback(htim);
#elseHAL_TIM_PeriodElapsedCallback(htim); //定时器溢出中断回调函数
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */}
} 在tim.c里重写定时器溢出中断回调函数 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim-Instance TIM2){HAL_UART_Transmit(huart1,helloworld,strlen(helloworld),1000);}
} 在main.c中启动定时器2的计数中断
HAL_TIM_Base_Start_IT(htim2); 实验二软件定时器
HAL_Delay() 硬延时 cpu在等着达到延时时间后才会继续做其他工作
设计思想
1.设计定时器记录起始时间记录用户延时时间
typedef struct
{uint32_t start; //保存起始时间uint32_t delay; //保存延时时间
}MyTim;
2.提供一个用于传递定时时间的软件定时器配置函数
//定时器初始化函数
void setTim(MyTim *timer,uint32_t delayms)
{timer-start HAL_GetTick(); timer-delay delayms;
}
3.提供一个用于比对是否达到定时要求的函数
uint32_t compareTim(MyTim *timer)
{if(HAL_GetTick() - timer-start timer-delay){return 1; //返回1说明达到了定时要求}else{return 0; }
} HAL_Delay()分析2 PWM模式解析可以在中文参考手册这找到 今天两个知识点
输入捕获用于捕获外部事件比如引脚的电平变化记录变化时间
用于测量外部信号的频率或某个电平持续时间。
输出比较用于控制输出一个波形用计数器跟比较寄存器进行比对
做出相应动作比如翻转电平通常用于产生PWM方波信号。 实验三通过定时器产生PWM信号驱动蜂鸣器
蜂鸣器是什么
采用直流电压供电的一个电子讯响器。
蜂鸣器分类
有源蜂鸣器内部带有震荡源一通电就可以震荡发出响声驱动较容易。 因为是内部集成好的震荡电路所以频率是固定的。
无源蜂鸣器内部没有震荡源直流电无法驱动所以用一个方波信号来进行驱动 价格便宜且频率可控。需要通过编程控制声调和响度驱动稍麻烦。
方法一通过给D1管脚输出高低电平来驱动蜂鸣器发声
将D1对应的管脚PB8配置成GPIO_OUTPUT
在main.c中
while (1)
{HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_7);HAL_Delay(1);
} 方法二定时器控制蜂鸣器发声
计数器寄存器 (TIMx_CNT)
自动装载寄存器 (TIMx_ARR)
捕获/比较寄存器(TIMx_CCRx)
输出过程
当0-t1这段时间计数器寄存器的CNT的值是小于CCR输出低电平。
当t1-t2这段时间计数器寄存器的CNT的值是大于CCR且小于ARR的输出高电平。
当CNT的值达到ARR里的值时产生溢出事件自动清零再次从0开始向上计数。
实验步骤
查看原理图 蜂鸣器模块原理 - D1 底板原理图 - D1 - 核心板底座 核心板原理图 - 核心板插针 - PB7
CubeMX配置 //将PB7配置成PWM信号的输出端 1.将时钟主频配置48Mhz 2.因为PB7管脚只对应TIM17的输出通道因此需要启动TIM17定时器 TIM17 - act - 选择PWM输出通道CH1N 分频系数 48-1 48Mhz的时钟经过48分频得到1Mhz的时钟频率 Counter 5000-1 相当于给到ARR寄存器 自动重装初值 Pulse 2500 脉冲计数个数即为高电平持续的时间 - 占空比 时钟频率是1Mhz计一个数就是1/1000000s即1微秒计5000个数则需要5ms
因此得知生成的PWM信号的一个周期就是5ms 频率即为时间的倒数
所以频率就是1 / 0.005s 200Hz。 占空比高电平占用整个周期的时间 0-2500是输出高电平信号的2500到5000是输出低电平高电平持续时间占整个周期的50% 所以该PWM信号的占空比即为50%
编写代码 //启动TIM17定时器输出PWM信号 HAL_TIMEx_PWMN_Start(htim17,TIM_CHANNEL_1); 周期 - 频率 周期越短频率越高则音调越高尖 周期越长频率越低则音调越低闷 脉冲 - 占空比 高电平持续时间越长响度越大 高电平持续时间越短响度越小
day6
脉宽调制和正弦信号发生器
有这样一个波形 这叫脉宽调制有人万一说脉宽调制这个词至少大概能想到有个在PWM这 简单处理一下可以变成这种正弦的波形 想做一个STM正弦的信号发生器有一个最简单的方法就是使用SPWM就是直接在TIM定时器引脚这里输出一个SPWM这样的情况下外面串一个电阻并一个电容就出来正弦波了这是最简单的一个信号发生器也是最快速的一个。
有面试要问的话知道这个肯定更好。
SPWM_百度百科 (baidu.com)
PWM的全称是Pulse Width Modulation脉冲宽度调制它是通过改变输出方波的占空比来改变等效的输出电压。广泛地用于电动机调速和阀门控制比如电动车电机调速就是使用这种方式。
所谓SPWM全称是Sinusoidal Pulse Width Modulation正弦脉宽调制就是在PWM的基础上改变了调制脉冲方式脉冲宽度时间占空比按正弦规律排列这样输出波形经过适当的滤波可以做到正弦波输出。它广泛地用于直流交流逆变器等比如高级一些的UPS就是一个例子。三相SPWM是使用SPWM模拟市电的三相输出在变频器领域被广泛的采用。 定长接收、不定长接收
通过包头包尾来确定确定一开头就证明需要用的数据开始传了然后再往后走 CubeMX生成PWM驱动蜂鸣器 或者 实验步骤
查看原理图 蜂鸣器模块原理 - D1 底板原理图 - D1 - 核心板底座 核心板原理图 - 核心板插针 - PB7
CubeMX配置 //将PB7配置成PWM信号的输出端 1.将时钟主频配置48Mhz 2.因为PB7管脚只对应TIM17的输出通道因此需要启动TIM17定时器 TIM17 - act - 选择PWM输出通道CH1N 分频系数 48-1 48Mhz的时钟经过48分频得到1Mhz的时钟频率 Counter 5000-1 相当于给到ARR寄存器 自动重装初值 Pulse 2500 脉冲计数个数即为高电平持续的时间 - 占空比 时钟频率是1Mhz计一个数就是1/1000000s即1微秒计5000个数则需要5ms
因此得知生成的PWM信号的一个周期就是5ms 频率即为时间的倒数
所以频率就是1 / 0.005s 200Hz。 占空比高电平占用整个周期的时间 0-2500是输出高电平信号的2500到5000是输出低电平高电平持续时间占整个周期的50% 所以该PWM信号的占空比即为50%
编写代码 //启动TIM17定时器输出PWM信号 HAL_TIMEx_PWMN_Start(htim17,TIM_CHANNEL_1); 周期 - 频率 周期越短频率越高则音调越高尖 周期越长频率越低则音调越低闷
脉冲 - 占空比 高电平持续时间越长响度越大 高电平持续时间越短响度越小 滴滴滴滴滴 每个定时器有4个通道每个通道都有一个捕获比较寄存器即获取CNT的值与CCRx进行比较通过比较输出高低电平以此来实现对脉宽的调制PWM
TIMx_ARR寄存器确定PWM频率
通过输入的重装载值值越大计的数越多所以就越慢
TIMx_CCRx寄存器确定占空比
比较寄存器的值越大占空比越小
刚刚设置的是100然后上面设置的是5000如果想把占空比调大100得变小 PWM模式1向上计数 计数器从0加到ARR自动重装载值计数器溢出然后计数器归为0继续加循环
PWM模式1向下计数 计数器从ARR自动重装载值 减到0计数器溢出。然后计数器归为ARR继续减循环 可以在中文手册里查引脚 补充占空比 DMA
【STM32】 DMA原理步骤超细详解一文看懂DMA_Z小旋的博客-CSDN博客_stm32 dma
DMA简介
DMA全称Direct Memory Access即直接存储器访问。
DMA 传输方式无需 CPU 直接控制传输也就是CPU告诉一下就可以了然后就开始搬运就行了也没有中断处理方式那样保留现场和恢复现场的过程通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路能使 CPU 的效率大为提高。 ●5 个独立的可配置通道 ( 请求 )
● 每个通道都直接连接专用的硬件 DMA 请求每个通道都同样支持软件触发。这些配置通
过软件来完成。
● 在同一个 DMA 模块上多个请求间的优先权可以通过软件编程设置 ( 共有四级很高、高、
中等和低 ) 优先权设置相等时由硬件决定 ( 请求 1 优先于请求 2 依此类推 ) 。
● 独立数据源和目标数据区的传输宽度 ( 字节、半字、全字 ) 模拟打包和拆包的过程。源
和目标地址必须按数据传输宽度对齐
● 支持循环的缓冲器管理
● 每个通道都有 3 个事件标志 (DMA 半传输、 DMA 传输完成和 DMA 传输出错 ) 这 3 个事
件标志逻辑或成为一个单独的中断请求。
● 存储器和存储器间的传输
● 外设到存储器和存储器到外设外设到外设间的传输
● 闪存、 SRAM 、 APB 和 AHB 外设均可作为访问的源和目标
● 可编程的数据传输数目最大为 65536
STM32F0-DMA通道 注可修改SYSCFG_CFGR1来配置通道的映射关系
STM32F0-DMA通道的优先级
仲裁器根据优先级管理着通道的请求和启动外设 / 存储器的访问
优先级管理分两个方面
● 软件可通过 DMA_CCRx 寄存器配置每个通道的优先级优先级分个等级 最高优先级 高优先级 中等优先级 低优先级
● 硬件如果 2 个请求有相同的软件优先级则较低编号的通道比较高编号的通道有较高
的优先权。举个例子通道 2 优先于通道 4 。
STM32F0-DMA传输
DMA传输模式
1个DMA控制器5个可独立配置的通道。所有通道都支持memory to memory的传输、外设到外设的传输、以及外设和memory之间的传输。
DMA传输的源、目的、长度
DMA_CPARx 寄存器 设置外设寄存器地址
DMA_CMARx 寄存器设置存储器地址
DMA_CCRx 寄存器 配置数据的传输方向
如果是存储器到存储器模式需配置DMA_CCRx的MEM2MEM位
DMA_CNDTRx 寄存器 写入需要传输的数据量 (0 到 65535)
DMA_CCRx 寄存器中的 PSIZE 和 MSIZE 位
设置源和目的的数据宽度,两边的位宽尽量保持一致
DMA增量设置
通过设置 DMA_CCRx 寄存器中的 PINC 和 MINC 标志位外设和存储器的指针在每次传输后可以有选择地完成自动增量
当设置为增量模式时下一个要传输的地址将是前一个地址加上增量值增量值取决与所选的数据宽度为 1 、 2 或 4 。
DMA循环模式
循环模式用于处理循环缓冲区和连续的数据传输 ( 如 ADC 的扫描模式 ) 。在 DMA_CCRx 寄存器中的 CIRC 位用于开启这一功能。
当启动了循环模式一组的数据传输完成时计数寄存器将会自动地被恢复成配置该通道时设置的初值 DMA 操作将会继续进行。 STM32F0-DMA中断 注这些标志位都在中断状态寄存器DMA_ISR中设置 使用DMA方式实现串口收发
配置 连续添加两个 这是5个优先级 在这个函数里写 extern uint8_t rx_buffer[100]; // 接收数据的数组
extern volatile uint8_t rx_len; // 接收数据的长度
extern volatile uint8_t recv_end_flag; // 接收结束标志位 然后回到main.c 编译烧录打开串口调试助手
附 右键跳转后发现
STM32模数转换器ADC
STM32-ADC模数转换概述
ADC简介
ADC是一个逐次逼近型的模数转换器可以将连续的模拟信号转换成离散的数字信号。
模拟信号电压、温度、光照、压力....传感器可以将非电学量转换成电学量
最直观的体现模拟信号是连续变化的曲线而数字量是不连续的一个个离散的点。 ADC的作用
采集传感器的数据测量输入电压检查电池电量剩余监测温湿度等。
ADC的性能指标
量程能测量的电压范围
分辨率ADC的分辨率通常以输出二进制数的位数表示位数越多分辨率越高一般来说分辨率越高转化时间越长。 转化时间模拟输入电压在允许的最大变化范围内从转换开始到获得稳定的数字量输出所需要的时间称为转换时间
就是从左到右这一整个周期所用到的时间。这里就涉及到时钟了。
STM32的ADC简介
12 位 ADC 是一种逐次逼近型模拟数字转换器。
它有多达 19 个通道可测量 16 个外部通道从外部GPIO口连接的16通道模拟输入
3个内部信号源分别为内部温度传感 (VSENSE) 输入、内部参考电压 (VREFINT) 输入、外部电池 VBAT 供电引脚输入 各通道的 A/D 转换可以单次、连续、扫描或间断模式执行。
ADC的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。 STM32F0-ADC特性
12位精度下转换速度可高达1MHz
可配置的转换精度6位8位10位12位就是上边画的采集点位的问题
转换电压范围0 ~ 3.6VV SSA ~ V DDA
供电范围2.4V ~ 3.6V
19个转换通道 16个外部通道、 3个内部通道
采样时间可配置
ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中 STM32F0-ADC时钟
APB时钟的2或4分频最高14MHz
优点不会有时钟域之间的同步带来的抖动触发事件和转换的起始时刻之间的延迟是确定 的从 而保证转换之间的时间间隔是固定的
缺点 ADC的转换时间和系统时钟频率相关受系统频率的影响较大
片上14MHZ HSI RC振荡器
优点无论MCU的运行频率都可以保证最高的ADC工作频率可以使用自动节电模式自动开启或关闭14MHz的内部振荡器
缺点触发信号的同步会带来抖动触发事件和转换的起始时刻之间的延迟不确定 STM32F0-ADC通道的选择 多通道就是两个以上的口都想进来那怎么办就轮询先采集一个再采集一个
19路复用通道
● 16 个从 GPIO 引脚引入的模拟输入 (ADC_IN0...ADC_IN15)
● 3 个内部模拟输入 ( 温度传感、内部参考电压、 VBAT 通道 )
ADC 可以转换一个单一通道或自动扫描一个序列通道。被转换的通道序列必须在通道选择寄存器 ADC_CHSELR 中编程选择每个模拟输入通道有专门的一位选择位 (CHSEL0...CHSEL18).
STM32F0-ADC转化模式
可以看到优缺点了
连续转换的占用资源单次转换的转换的没多通道的及时但是工程上常用的是单次转换首先占用的资源少其次可以控制想让它转换时就转换不想转换的时候就不给它使能就不转换了。
注
ADC 通知应用每次转换结束 (EOC) 事件
ADC 通知应用每次序列转换结束 (EOS) 事件。
这些标志位都是在ADC 中断和状态寄存(ADC_ISR)中
ADC_CFGR1可配置COUNT位 。
STM32F0-ADC转化时间
可编程采样时间 (SMP)
T Sampling 可配置 SMP[2:0]ADC_SMPR
需要和外部电路的输入阻抗匹配采样时间适用于所有通道
转化的时间 T conversion 取决于转换精度 RES[1:0]ADC_CFGR1
每个通道总的转换时间等于
T Sampling T conversion 上表可以看出精度越高需要的转换时间越多为什么呢 例如采样精度为12位ADC的时钟为14M
最小转化时间为
t CONV 1.5T 12.5T 14 T 1 µ
转换时间快速预览表 不需要高转换精度的应用可以通过降低精确度来提高转换速度 假设ADC模块工作在14MHz的最高工作频率下 STM32F0-ADC触发方式
软件触发
软件设置ADC_CR的ADSTART1 时触发选择有效。
外部事件触发
外部事件 ( 例如定时器TRGO、输入引脚 ) 触发可以设置触发源以及触发极性 STM32F0-ADC模拟看门狗 大概是这么个意思
就是设置一个电压门槛类似PWM比较器比如设置3V那么外部电压采集到3V了就会立刻跳到一个中断里。比如到3V了就置一个1然后识别到1了就赶紧干一个活去。
还有软件上的看门狗的
程序在一直运行过程中你不知道这个程序有没有卡死这个看门狗的作用就是看着点看着有没有死机
就比如说约定好了每过10分钟去喂一次狗但是有一次到了点没有去喂就说明在忙着还没有出来赶紧想办法把忙着的弄出来
可以去给一个参数1每运行一次给一次这样的话时间久了如果程序卡死了这个参数得不到变化了就知道卡死了或者可以给一个灯来指示报警或者重启其实最简单的方法就是直接给一个重启的指令然后它重启了这样就可以了
检测待转换的模拟电压 电压超出检测范围就置位AWDADC_ISR并条件性地产生中断
检测范围由上下门限寄存器指定、 12位的ADC_HTR和ADC_LTR有效值
模拟看门狗的使能控制
AWDENADC_CFGR1 检测所有通道还是单个通道由AWDSELADC_CFGR1决定 检测哪个单个通道由AWDCH[4:0]ADC_CFGR1决定
附VSCode打开文件后中文注释乱码了 有一个通过内容猜测
然后就不乱码了 光敏电阻电路原理图 STM32CubeMX配置 IN4是输入的第4个通道
然后去找ADC功能(不用改)
时钟
依旧是把外部时钟设置成48MHz的
实验一单通道单次采集实验 - 火焰传感器采集
分析原理图 火焰传感器模块 - OUT - D2 - 高低电平 - IN- - A1 - 模拟量 (ADC采集该管脚即可) 底板原理图 - A1 - 核心板底座 核心板原理图 - 核心板插针 - A1 - PA4
CubeMX配置 UART1 - 异步模式 - 115200bit/s 用串口看的话就这么配置 火焰传感器 - A1 - PA4 - ADC_IN4
代码编写
uint32_t fire_value;
while(1)
{HAL_ADC_Start(hadc); //启动ADCHAL_ADC_PollForConversion(hadc,100); //等待转换fire_value HAL_ADC_GetValue(hadc); //转换完成后将值赋给fire_valueprintf(fire %d\n,fire_value);HAL_ADC_Stop(hadc);HAL_Delay(1000);
} 再写一个重定向函数让其在串口中显示数据 int fputc(int ch, FILE *f) //重定向函数
{while (!(USART1-ISR (1 7)));USART1-TDR ch;return ch;
} 插上火焰传感器烧录打开串口调试助手
实验二多通道单次采集实验 - 采集按键值和火焰值
1.CubeMX配置 UART1 - 异步模式 - 115200bit/s 火焰传感器 - A1 - PA4 - ADC_IN4 光照传感器 - A2 - PA6 - ADC_IN6 系统时钟 - 48M //时钟影响cpu存取速度
2.代码编写
uint32_t key,fire;
while (1)
{HAL_ADC_Start(hadc);while(!(ADC1-ISR (12))); //单个通道转换结束 EOC信号key HAL_ADC_GetValue(hadc);while(!(ADC1-ISR (13))); //序列转换结束 EOS信号fire HAL_ADC_GetValue(hadc);printf(key %d fire %d\n,key,fire);HAL_ADC_Stop(hadc);HAL_Delay(1000);
} 多通道是采集不同引脚的值
按键是单通道的因为只用一个引脚
代码截图 串口调试
任务二 蜂鸣器放音乐 五向按键不同方向控制不同灯效果 这儿为什么uint32_t呢下边的HAL_ADC_GetValue跳转可以看到返回的类型 多通道的话G030的板子是下边这样改F051的没改 火焰传感器值获取的 while(1){HAL_ADC_Start(hadc); //启动ADCHAL_ADC_PollForConversion(hadc,100); //等待转换fire_value HAL_ADC_GetValue(hadc); //转换完成后将值赋给fire_valueprintf(fire %d\n,fire_value);HAL_ADC_Stop(hadc);HAL_Delay(1000); } 注意G030的需要把hadc换成hadc1 PWM呼吸灯
这是G030的051的CUbemx配置好之后把主函数复制黏贴就能用 呼吸灯的占空比是不断变化的找一个函数至少的功能是可以调整占空比数值
while里循环改变占空比设一个变量加到一个数然后清零然后-----
配置 main.c中 uint16_t pwmValue0;
uint8_t dir0; int main(void):
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(htim3,TIM_CHANNEL_3);
/* USER CODE END 2 */ /* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if(dir0){pwmValue5; // 改变占空比,下边有函数的if(pwmValue500)dir1;}else{pwmValue-5;if(pwmValue0)dir0;}__HAL_TIM_SetCompare(htim3,TIM_CHANNEL_3,pwmValue); // pwmValue在这里传了参数的HAL_Delay(10);
}
/* USER CODE END 3 */ SPI
spi常用的除了这个LCD屏幕之外还有FLASH、ADC等
是全双工通信 LCD显示屏 1. 选择一张图片 - 后缀名修改为xx.bmp 2. 用电脑工具画图 - 打开图片 - 重新调整大小 - 像素 - 128*128 - 保持纵横比去掉 - 保存 3. 图片取模软件 - Image2Lcd 2.9(破解版) - Img2Lcd.exe - C语言数组 水平扫描 16位真彩色 128*128像素 不勾选包含图像头 5. Lcd_Init(); //初始化 Lcd_Clear(RED); //清屏 HAL_Delay(1000); //延时一短时间 showimage(gImage_xx); //传入图片的数组名 将lcd源码的.c和.h文件放在工程目录对应的位置下。
液晶
1某些物质在熔融状态下具备液体的流动性保留了部分晶体物质分子的有序排列
形成一种兼有晶态和液态部分形式的中间态。
2 在通电状态下可以有序排列使光线容易通过
在不通电状态下排列混乱阻止光线通过。
液晶显示屏的显色原理
液晶显示屏必须要有背光源提供背光荧光灯投射出光源先经过偏光片到达液晶层通过通断电控制液晶的排列方式进而改变穿过液晶层的光线角度再经过滤光片和偏光片之后就能投射出不同颜色的光。因此改变刺激液晶排列方式的电压进而实现对最终呈现颜色和亮度的控制。
24位真彩色
R:8位
G:8位
B:8位
颜色深度2^8 2^8 2^8
STM32F051开发板的板载显示屏是1.44寸的TFT液晶显示屏
128*128 16位色 RGB565
R:5
G:6
B:5
颜色深度2^5 2^6 2^5 R G B
红色 11111 000000 00000 SPI通信总线
1.概念 SPI接口是同步全双工三线/四线串行总线采用主从模式架构一个主机多个从机 四线制
MOSI : 数据线 主设备数据输出从设备数据输入
MISO 数据线 主设备数据输入从设备数据输出
SCLK 时钟线 主机产生时钟信号
SS 片选线 由主机控制选择从机设备低电平有效
单主机单从机一对一时SS片选线接低电平即可从机永远选中采用三线制通信即可。
SPI通信协议 起始信号SS由高到低是SPI通信起始信号 起始信号SS由低到高是SPI通信起始信号 数据传输SPI采用MOSI和MISO信号线进行数据传输的使用SCK时钟信号线进行同步。 极性(Clock Polarity ,CPOL) : 决定着时钟起始电平 相位(Clock Phase ,CPHA) 决定采样边沿
SPI有四种通信模式 当CPHA为0是sck时钟线为奇数边沿采样 1CPOL0空闲状态是时钟为低电平 2CPOL1空闲状态是时钟为高电平 当CPHA为1是SCK时钟线为偶数边沿采样 1CPOL0空闲状态是时钟为低电平 2CPOL1空闲状态是时钟为高电平 模式 CPOL CPHA 采样时刻 空闲时SCK电平 0 0 0 奇数 低 1 0 1 偶数 低 2 1 0 奇数 高 3 1 1 偶数 高 在SPI操作中最重要的两项设置就是时钟极性CPOL和时钟相位CPHA这两项即是主从设备间数据采样的约定方式 实验一LCD显示屏进行单色显示
1.查看原理图 PA15 - PB6 配置CubeMX RCC - 48M 左侧connective - SPI - Full(全双工主机) hardware NSS - output PA15 - SPI_NSS PB3 - SPI_SCK PB4 - SPI_MISO PB5 - SPI_MOSI PB6 - GPIO_OUTPUT 选好之后去修改时钟分频值 4 data size8(每一个像素点是一个16位数是由两个八位数字拼接起来的) 生成工程把源文件粘贴到对应的文件夹下面 .c - src .h - inc application/user - 右键添加已经存在的文件 全编译 2.调用函数 Lcd_Init(); Lcd_Clear(YELLOW);
实验二 屏幕显示图片 1. 选择一张图片 - 后缀名修改为xx.bmp(有时候直接改可能是win11的事去画图里另存为了修改) 2. 用电脑工具画图 - 打开图片 - 重新调整大小 - 像素 - 128*128 - 保持纵横比去掉 - 保存 3. 图片取模软件 - Image2Lcd 2.9(破解版) - Img2Lcd.exe - C语言数组 水平扫描 16位真彩色 128*128像素 不勾选包含图像头 4. 保存成xx.h的文件 - 粘贴到inc目录下 - 回到工程 #include xx.h 5. Lcd_Init(); //初始化 Lcd_Clear(RED); //清屏 HAL_Delay(1000); //延时一短时间 showimage(gImage_xx); //传入图片的数组名
实验三 屏幕显示英文 1. 打开文字取模软件 - PCtoLCD2002.exe 2. 选项 - 阴码 逐行式 C51格式 顺向 16*8(表示生成的字符宽8高16) 根据这种方式就能制作8*16的ASCII码字库 Gui_DrawFont_GBK16(10,10,BLACK,WHITE,farsight);