当前位置:网站首页>三.芯片启动和时钟系统
三.芯片启动和时钟系统
2022-07-02 07:33:00 【车水码浓】
芯片启动和时钟系统
1.芯片启动
首先stm32会根据启动方式(参考手册2.4节)从启动位置加载启动代码到内存中,之后开始执行启动代码,一般启动代码使用官方提供的即可 ---------- xxx.s
启动代码的工作:
初始化堆栈空间,定义异常向量表 调用SystemInit ----------- 系统初始化 初始化时钟,调整异常向量表 执行main ---------- 主函数
芯片要开始工作,必须初始化时钟和内存,stm32的内存使用片内SRAM,可以直接使用,时钟需要初始化,ARM芯片需要定义异常向量表,执行C语言代码必须初始化堆栈。
stm32f407推荐的主时钟频率 168MHz
2.产生原始频率的硬件
(1)晶振
(2)RC(LC)振荡电路
原始频率不会很高,使用前必须升频,升频使用PLL(升频)电路
CPU时钟系统的大体结构
3.stm32f407的原始时钟
HSI RC -------------- 高速内部振荡时钟 16M HSE OSC ------------- 高速外部晶振 4~26M(8M) //以上两个时钟源可以直接作为系统主时钟,也可以通过PLL升频后作为主时钟 LSI RC --------------- 低速内部振荡时钟 32K ----- 看门狗 LSE OSC -------------- 低速外部晶振 32.768K ----- RTC
stm32f407的时钟树
PLL的输出时钟 = PLL输入时钟 X PLLN / PLLM / PLLP
168M = 8M X 336 / 8 / 2
4.将keil5的工程的系统时钟配置为168MHz
(1)修改system_stm32f4xx.c的254行
#define PLL_M 8
(2)修改stm32f4xx.h的127行
//该文件是只读属性文件,要去文件系统中找到该文件,去掉只读属性 #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
练习:
将系统主频配置为168M
修改PLL,调节系统主频
#define PLL_N 336//168M #define PLL_N 432//216M 超频 #define PLL_N 168//84M 降频
系统总线时钟频率:
SYSCLK时钟 ------------ 168MHz HCLK/AHB总线 ---------- 168MHz APB1时钟 -------------- 42MHz APB2时钟 -------------- 84MHz
__________________________________________________________________________________________________________________________________________________________
按键驱动
1.看原理图
从原理图可知:
按键松开 -------- 引脚高电平
按键按下 -------- 引脚低电平
按键对应的引脚:
S1 ----- PA0
S2 ----- PE2
S3 ----- PE3
S4 ----- PE4
如何读取输入引脚的电平
(1)读取输入数据寄存器(IDR)对应位的值 1 ----- 输入高电平 0 ----- 输入低电平
(2)位段操作 PAin(0)==0 ----- 输入低电平 PAin(0)==1 ----- 输入高电平
(3)库函数 uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //传入哪一组哪个脚,返回该引脚的电平
——————————————————————————————————————————————————————————————————————————————————————
练习:
完成其他三个按键的检测程序,分别使用 寄存器 位段 库函数判断
实现一下功能:
按下S2,D2亮 按下S3,D3亮 按下S4,D4亮
//key.c
#include <stm32f4xx.h>
#include <key.h>
void key_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
//1.开启GPIOA的时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOE,ENABLE);
//2.GPIO初始化 PA0
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;//输入模式
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;//无上下拉
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;//PA0
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;//PE2 PE3 PE4
GPIO_Init(GPIOE,&GPIO_InitStruct);
//main.c
#include <stm32f4xx.h>
#include <led.h>
#include <sys.h>
#include <key.h>
int main()
{
int key_flag = 0;
//初始化
led_init();
key_init();
while(1){
if(S1==0){
//延时消抖10ms
delay(100);
if(S1==0){
//真实按键事件
if(key_flag==0){//按下没有松开
D1 = ~D1;//取反
key_flag = 1;
}
}
}
else{
//延时消抖10ms
delay(100);
if(S1){
key_flag = 0;
}
}
}
}
//lcd.c
include <stm32f4xx.h>
#include <led.h>
void delay(unsigned int ms)
{
int i,j;
for(i=0;i<ms;i++)
for(j=0;j<5000;j++);
}
void led_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
//1.开启GPIOE GPIOF的时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOF,ENABLE);
//2.GPIO初始化 PF9 PF10 PE13 PE14
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;//输出模式
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//高速
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;//无上下拉
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;//PF9 PF10
GPIO_Init(GPIOF,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14;//PE13 PE14
GPIO_Init(GPIOE,&GPIO_InitStruct);
//3.LED默认关闭
GPIO_SetBits(GPIOF,GPIO_Pin_9|GPIO_Pin_10);
GPIO_SetBits(GPIOE,GPIO_Pin_13|GPIO_Pin_14);
}
//lcd.h
#ifndef _LED_H_
#define _LED_H_
#define D1 PFout(9)
#define D2 PFout(10)
#define D3 PEout(13)
#define D4 PEout(14)
void delay(unsigned int ms);
void led_init(void);
#endif
//key.h
#ifndef _KEY_H_
#define _KEY_H_
#define S1 PAin(0)
#define S2 PEin(2)
#define S3 PEin(3)
#define S4 PEin(4)
void key_init(void);
#endif
//sys.h 该文件由系统定义
#ifndef __SYS_H_
#define __SYS_H_
#include "stm32f4xx.h"
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+20) //0x40020014
#define GPIOB_ODR_Addr (GPIOB_BASE+20) //0x40020414
#define GPIOC_ODR_Addr (GPIOC_BASE+20) //0x40020814
#define GPIOD_ODR_Addr (GPIOD_BASE+20) //0x40020C14
#define GPIOE_ODR_Addr (GPIOE_BASE+20) //0x40021014
#define GPIOF_ODR_Addr (GPIOF_BASE+20) //0x40021414 20 = 0x14
#define GPIOG_ODR_Addr (GPIOG_BASE+20) //0x40021814
#define GPIOH_ODR_Addr (GPIOH_BASE+20) //0x40021C14
#define GPIOI_ODR_Addr (GPIOI_BASE+20) //0x40022014
#define GPIOA_IDR_Addr (GPIOA_BASE+16) //0x40020010 16 = 0x10
#define GPIOB_IDR_Addr (GPIOB_BASE+16) //0x40020410
#define GPIOC_IDR_Addr (GPIOC_BASE+16) //0x40020810
#define GPIOD_IDR_Addr (GPIOD_BASE+16) //0x40020C10
#define GPIOE_IDR_Addr (GPIOE_BASE+16) //0x40021010
#define GPIOF_IDR_Addr (GPIOF_BASE+16) //0x40021410
#define GPIOG_IDR_Addr (GPIOG_BASE+16) //0x40021810
#define GPIOH_IDR_Addr (GPIOH_BASE+16) //0x40021C10
#define GPIOI_IDR_Addr (GPIOI_BASE+16) //0x40022010
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
#define PHout(n) BIT_ADDR(GPIOH_ODR_Addr,n) //输出
#define PHin(n) BIT_ADDR(GPIOH_IDR_Addr,n) //输入
#define PIout(n) BIT_ADDR(GPIOI_ODR_Addr,n) //输出
#define PIin(n) BIT_ADDR(GPIOI_IDR_Addr,n) //输入
#endif
3.按键消抖————延时消抖
以上按键程序不管是否有按键事件发生,都会占用CPU来进行判断,这种方式叫做轮询,效率比较低,CPU提供了效率更高的方式 --------- 中断。
边栏推荐
- 二叉树专题--AcWing 19. 二叉树的下一个节点(找树中节点的后继)
- 1287_ Implementation analysis of prvtaskistasksuspended() interface in FreeRTOS
- 力扣(LeetCode)182. 查找重复的电子邮箱(2022.07.01)
- Luogu p1892 [boi2003] Gang (and search for variant anti set)
- JSP webshell免殺——JSP的基礎
- 【AI应用】海康威视iVMS-4200软件安装
- 二叉树专题--AcWing 18. 重建二叉树(利用前、中序遍历,构建二叉树)
- Jsp webshell Free from killing - The Foundation of JSP
- 【深入浅出玩转FPGA学习2----设计技巧(基本语法)】
- Special topic of binary tree -- Logu p1229 traversal problem (the number of traversals in the middle order is calculated when the pre and post order traversals of the multiplication principle are know
猜你喜欢
1287_ Implementation analysis of prvtaskistasksuspended() interface in FreeRTOS
使用华为性能管理服务,按需配置采样率
Matlab processing of distance measurement of experimental electron microscope
Dialogue Wu Gang: why do I believe in the rise of "big country brands"?
Implement custom drawer component in quick application
JSP webshell免殺——JSP的基礎
V2X-Sim数据集(上海交大&纽约大学)
【深入浅出玩转FPGA学习3-----基本语法】
The most detailed MySQL installation tutorial
Special topic of binary tree -- Logu p1229 traversal problem (the number of traversals in the middle order is calculated when the pre and post order traversals of the multiplication principle are know
随机推荐
二叉树专题--AcWing 47. 二叉树中和为某一值的路径(前序遍历)
PCL之滤波
Leetcode 182 Find duplicate email (2022.07.01)
【付费推广】常见问题合集,推荐榜单FAQ
点云投影图片
二叉树专题--洛谷 P1229 遍历问题(乘法原理 已知前、后序遍历求中序遍历个数)
PCL point cloud to depth image
UVM - configuration mechanism
Special topic of binary tree -- acwing 18 Rebuild the binary tree (construct the binary tree by traversing the front and middle order)
JVM garbage collector
如何用list组件实现tabbar标题栏
618 what is the secret of dominating the list again? Nike's latest financial report gives the answer
最详细MySql安装教程
The most detailed MySQL installation tutorial
The URL in the RTSP setup header of the axis device cannot take a parameter
学习open62541 --- [66] UA_String的生成方法
二叉树专题--AcWing 1589. 构建二叉搜索树
Dialogue Wu Gang: why do I believe in the rise of "big country brands"?
Open the encrypted SQLite method with sqlcipher
Hdu1234 door opener and door closer (water question)