1.LED的硬件连接(枭龙)
黄色LED灯D5(LED2) D6(LED1)分别连接PC5 ,PC4.
红色LED灯D4(LED3)连接PB0,输出高电平LED灯熄灭。(单片机管脚驱动能力有限,供阳设计将驱动能力交给电源)。
2.GPIO的HAL库介绍
GPIO操作HAL库函数分布文件:
头文件:stm32f1xx_gpio.h
源文件:stm32f1xx_gpio.c
重要函数:
1个初始化函数:
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx/*(对象,哪一个GPIO (ABCD..)*/, GPIO_InitTypeDef *GPIO_Init/*(属性)*/);
作用:初始化一个或者多个IO口(同一组)的工作模式,输入还是输出,输出类型、速度以及上下拉方式。也就是一组IO口的配置寄存器。
(GPIOx->CRL, GPIOx->CRH)
1个读取输入电平函数:
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx), uint16_t GPIO_Pin/*(哪一个引脚)*/);
作用:读取某个GPIO的输入电平。实际操作的是GPIOx_IDR寄存器。
示例:HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
1个设置输出电平函数
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
示例:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_2, GPIO_PIN_SET);
1个电平反转函数
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
示例:HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0|GPIO_PIN_2);
1个引脚电平锁定函数
HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
配置HAL库操作IO口步骤:
1.初始化HAL库:HAL_Init()。
2.初始化系统时钟 :SystemClock_Init( )。
3. 使能IO口时钟
操作寄存器:配置IO口时钟使能寄存器: RCC->APB2ENR
HAL库方法:__HAL_RCC_GPIOB_CLK_ENABLE();
或者__GPIOB_CLK_ENABLE();
4.初始化IO口模式。
操作寄存器:GPIOx_CRL CRH
HAL库方法:HAL_GPIO_Init();
5.操作IO口,输出高低电平。
操作寄存器:配置寄存器GPIOX_ODR或者GPIOx_BSRR 。
HAL库方法:HAL_GPIO_WritePin();
stm32f1xx_hal_conf.h:各个宏定义;(外设)
main.c
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
int main()
{
Stm32_Clock_Init(9);
//时钟初始化
delay_init(72);
//延时初始化
LED_Init();
//LED灯初始化
while(1)
{
LED1 = 0;
delay_ms(300);
LED2 = 0;
delay_ms(300);
LED3 = 0;
delay_ms(300);
LED1 = 1;
delay_ms(300);
LED2 = 1;
delay_ms(300);
LED3 = 1;
delay_ms(300);
}
}
led.h
#ifndef __LED_H
#define __LED_H
#include "sys.h"
#define LED1 PCout(4) //PC4
#define LED2 PCout(5) //PC5
#define LED3 PBout(0) //PB0
void LED_Init(void);
#endif
led.c
#include "led.h"
void LED_Init(void)
{
RCC->APB2ENR |= 1<<3; //PORTB时钟使能
RCC->APB2ENR |= 1<<4; //PORTC时钟使能
GPIOC->CRL &= 0xFFF0FFFF;
GPIOC->CRL |= 0x00030000; //推挽高速输出
GPIOC->ODR |= 1<<4;// PC4
GPIOC->CRL &= 0xFF0FFFFF;
GPIOC->CRL |= 0x00300000;
GPIOC->ODR |= 1<<5;//同理
GPIOB->CRL &= 0xFFFFFFF0;
GPIOB->CRL |= 0x00000003;
GPIOB->ODR |= 1;
}
学习加深印象吧,忍不住回头重新学习,根据自己的理解,解释一下代码,如果有错误欢迎在下面指出
main.c
#include "MyIncludes.h"//存放mian.c要使用的.h文件 有 #include "stm32f1xx.h" #include "stm32_types.h" #include"stm32_system.h" #include "delay.h"(延时函数) #include"led.h"
int main(void)
{
System_Init();//系统初始化,里面具体
//不懂,记住就好;
LED_Init();//LED初始化
while (1)
{
LED_Flash();//LED闪烁;
}
}
LED.h
#ifndef __LED_H_
#define __LED_H_
#include "stm32f1xx.h"
#include "stm32_types.h"
#include "stm32f1xx_hal.h"
#define LED1 1
#define LED2 2 //为什么要在这里将1 2
//分别宏定义为LED1 LED2,因为在LED.c中要使
//用switch(),定义后描述更方便。
void LED_Init(void);//LED初始化函数
void LED_Flash(void);//LED闪烁,这里STM32F10一共有三个LED灯
void LED_Open(u8 led);//LED 打开函数
void LED_Close(u8 led);//LED 关闭函数
#endif
LED.c
#include "led.h"
#include "delay.h"
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/*这里使用的是结构体变量声明为
GPIO_InitStruct; 结构体内有Pin(管脚)
Mode(模式),Pull(上拉方式)Speed(速度)*/
__GPIOB_CLK_ENABLE();
__GPIOC_CLK_ENABLE();
/*使能GPIOB,GPIOC时钟,因为LED的管脚分别
在 GPIOB GPIOC上,里面的不怎么太懂,
先记住就就好*/
GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;/*PD
4,PD5的LED*/
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;/*普通推挽输出模式*/
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;/*高速*/
GPIO_InitStruct.Pull = GPIO_NOPULL;/*上拉*/
HAL_GPIO_Init(GPIOC,&GPIO_InitStruct);//初始化GPIOC
GPIO_InitStruct.Pin = GPIO_PIN_0;//GPIOB0;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);/*这里是关闭LED,GPIO_PIN_SET = 1
高电平关闭。 HAL_GPIO_WritePin();设置输
出电平函数,也就是将PC4 PC5 PB0管脚置
为高电平*/
}
void LED_Flash(void)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5);
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
delay_ms(1000);
/*电平反转函数 也就是高变低 低变高;*/
}
void LED_Open(u8 led)
{
switch( led )
{
case (LED1):
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5,GPIO_PIN_RESET);break;
case (LED2):
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
break;//拉低亮
default : break;
}
}
void LED_Close(u8 led)
{
switch( led )
{
case (LED1):
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5,GPIO_PIN_SET);
break;
case (LED2):
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
break;
default : break;//高电平关闭
}
}
这个我是看了前20章,感觉到很懵,来深入学习一下把,我感觉HAL库很方便,但是我感觉没有寄存器直抒胸臆吧,是什么就是什么,HAL把内容封装在一起,可能我们知道怎么用,但是不知道为什么这样感觉就很尴尬,所以来了解一下吧。
System_Init(void)中的HAL_Init()函数
HAL_StatusTypeDef HAL_Init(void)
//结构体函数(可以返回结构体里面的值,也就是HAL库状态)
{
/* 配置闪存预取*/
#if (PREFETCH_ENABLE != 0)
#if defined(STM32F101x6) || defined(STM32F101xB) || defined(STM32F101xE) || defined(STM32F101xG) || \
defined(STM32F102x6) || defined(STM32F102xB) || \
defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG) || \
defined(STM32F105xC) || defined(STM32F107xC)
/* 值行设备上没有预取缓冲区 */
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
//这里看下面的1文字
//闪存预取缓冲区使能
#endif
#endif /* 闪存预取启用 */
/* 设置中断优先级
4位优先权子优先级为0位*/
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
/* 使用systick作为时基源并配置1毫秒时钟(重置后的默认时钟为MSI)*/
HAL_InitTick(TICK_INT_PRIORITY);
/* 初始化低级硬件*/
HAL_MspInit();
/*返回功能状态*/
return HAL_OK;
}
先配置闪存预取: 进入__HAL_FLASH_PREFETCH_BUFFER_ENABLE()闪存预取缓冲区使能函数 FLASH->ACR|=FLASH_ACR_PRFTBE(0x1U << 4 也就是 0x10000) 也就是0x4002 2000->ACR |= 0x10000,也就是启用预取缓冲区
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4)设置中断优先级函数
void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
/* 检查参数是否为0 ((void)0)函数的运用*/
assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
/* 根据PriorityGroup参数值设置PRIGROUP[10:8]位*/
NVIC_SetPriorityGrouping(PriorityGroup);
}
2.2 NVIC_SetPriorityGrouping(PriorityGroup);
__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
//内联函数
{
uint32_t reg_value;
uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* 仅使用值0..7 */
reg_value = SCB->AIRCR; /* 读取旧寄存器配置->应用中断和复位控制寄存器 */
reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* 清除要更改的位 */
reg_value = (reg_value |
((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
(PriorityGroupTmp << 8U) ); /* 插入写入密钥和优先级组 */
SCB->AIRCR = reg_value;
}
/*配置SysTick,使其在1毫秒内中断 72000000;/10000*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/*Configure the SysTick IRQ priority */
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority ,0);
/* Return function status */
return HAL_OK;
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
{
return (1UL);
/* 无法重新加载值 */
}
SysTick->LOAD = (uint32_t)(ticks - 1UL);
/* 设置重新加载寄存器 */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
/*设置Systick中断的优先级*/
SysTick->VAL = 0UL;
/* 加载SysTick计数器值 */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
/* 启用SysTick IRQ和SysTick计时器 */
return (0UL);
/* 函数成功 */
}