?ok,今天的学习 就先结束啦? o(* ̄▽ ̄*)ブ
本来想从寄存器开始学的,但是放弃了,直接从从库函数开始了
(主要是因为没能找到手册 ,,???,, )
使用的板子呢,是好久好久好久好久之前买的小熊派的板子(刚刚甚至去淘宝看了下,比之前还涨了几块钱,也不记得当时是不是用卷)
芯片是STM32L431RC,今天就的内容就是基础的“点灯”和“按键”
因为是用的STM32CubeMX生成的工程,初始化部分就直接配好了,去学习库函数也很方便,先紧着用到的看,其他的先放着
(话说,之前年轻不懂事,觉得库函数用起来比寄存器难,就是因为我不会用STM32CubeMX,初始化个GPIO口看半天手册,结果结构体还配错了!淦!)
先说结论:
灯,配好了;但是只做了常亮和闪烁,呼吸灯没做,因为板子只有一个灯,流水灯也没做
按键,配好了;但是按键控制灯的部分有点瑕疵。记忆中,是可以做到很稳定的开关灯的。但是这次没有做出来,应该是哪个部分的判断逻辑没写好。晚上再想想。
中断,配好了(给按键用的);这个直接STM32CubeMX配好了,没有难度,就是创建的时候,上升沿下降沿让我纠结了下,当时脑子完全短路了,看百度百科都差点内看懂。不过,有点小问题,我记得进入中断后,要重置中断标志位的,但是没看懂STM32CubeMX怎么写的。在看了在看了。。。
再说过程:
#1?通过STM32CubeMX配置当前需要使用的端口
PH0とPH1:RCC
PC13:LED灯链接的端口,被配置为输出,推挽 (注1)
PB2:KEY1按键链接的端口,被配置为输入,上拉(注1)
PB3:KEY2按键链接的端口,被配置为中断,下降沿检测(注1)
EXTI3:PB3对应的中断
#2 生成MDK使用的代码(以及手册)
说真的,我是真没想到,还能生成当前配置的手册;真是太好了,像我这种连上升沿下降沿都忘记的人,忘记哪个端口配置的哪个模式,很正常吧?但是呢,现在我有了手册,再不用写两行就去看下配置函数和原理图了!!!直接看手册辣!!!!((●ˇ?ˇ●))
生成的配置手册
至于代码部分,那就是今天最主要的东西了!!!!
固件库真是太贴心了,注释写的真是太详细了,一个一个函数的看过去,太满足了。
(虽然并没有看懂原理,但是我看懂了用法。( ̄??) )
比方说,这个函数
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
按照?GPIO_Init?中指定的配置,初始化GPIOx。
而?GPIO_Init 里面的配置,则包括下面这些
typedef struct
{
?uint32_t Pin; ? ? ? ?//GPIOx 的某个引脚,例如PC13 ,GPIOC的GPIO_PIN_13,这里就可以赋值为GPIO_PIN_13
?uint32_t Mode; ? ? ? //这个就是引脚的状态了,输入?输入?复用?都是通过这个引脚进行配置的
?uint32_t Pull; ? ? ? //用于配置引脚的下拉下拉的,这个一般是输入用的,不需要就直接配置为NOPULL就好了
?uint32_t Speed; ? ? ?//端口的频率,根据需要和端口的实际支持情况来配咯
?uint32_t Alternate; ? //端口是否复用,没有到就直接不管他就可以了
} GPIO_InitTypeDef;
这些结构体成员都是可以通过固件库自带的宏进行复制的,大概整理了下,是下面这个样子的
//指定模式 mode
GPIO_MODE_INPUT // 输入模式
GPIO_MODE_OUTPUT_PP // 推挽输出
GPIO_MODE_OUTPUT_OD //开漏输出
GPIO_MODE_AF_PP //复用推挽
GPIO_MODE_AF_OD //复用开漏
GPIO_MODE_ANALOG //模拟模式
GPIO_MODE_ANALOG_ADC_CONTROL //模数转换控制
GPIO_MODE_IT_RISING //外部中断上升沿检测
GPIO_MODE_IT_FALLING //外部中断下降沿检测
GPIO_MODE_IT_RISING_FALLING // 外部中断上升和下降沿检测
GPIO_MODE_EVT_RISING //外部事件上升沿检测
GPIO_MODE_EVT_FALLING //外部事件下降沿检测
GPIO_MODE_EVT_RISING_FALLING // 外部事件上升和下降沿检测
?
//指定频率 speed
GPIO_SPEED_FREQ_LOW //5MHz的频率
GPIO_SPEED_FREQ_MEDIUM //5-25MHz频率
GPIO_SPEED_FREQ_HIGH //25-50MHz频率
GPIO_SPEED_FREQ_VERY_HIGH //50-80MHz频率
//指定上下拉 ?pull
GPIO_NOPULL //无上拉和下拉电阻
GPIO_PULLUP //上拉电阻
GPIO_PULLDOWN //下拉电阻
至于其他相关使用到的函数接口,如下
//读取某个GPIO口的某个引脚的输入
GPIO_PinState ? ? HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//改变某个GPIO口的某个引脚的输出
void ? ? ? ? ? ? ?HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
//反转某个GPIO口的某个引脚的输出
void ? ? ? ? ? ? ?HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//处理某个引脚的中断请求
void ? ? ? ? ? ? ?HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin);
//EXTI3的中断处理函数
void EXTI3_IRQHandler(void);
这些函数的用法呢,也都是直接根据需要去传参就好了。因为今天就只是端口控制按键和灯,参数里面的状态也都是RESET/SET这两个了
这里面呢,中断处理的函数,我还没看懂,我记得是需要重置中断标志位的,这个咋重置的呢??好迷茫啊。。。。。
注1?GPIO配置函数
void MX_GPIO_Init(void)
{
?GPIO_InitTypeDef GPIO_InitStruct = {0};
?/* GPIO Ports Clock Enable */
?__HAL_RCC_GPIOC_CLK_ENABLE();
?__HAL_RCC_GPIOH_CLK_ENABLE();
?__HAL_RCC_GPIOB_CLK_ENABLE();
?/*Configure GPIO pin Output Level */
?HAL_GPIO_WritePin(LED_GPIO_PC13_GPIO_Port, LED_GPIO_PC13_Pin, GPIO_PIN_RESET);
?/*Configure GPIO pin : PtPin */
?GPIO_InitStruct.Pin = LED_GPIO_PC13_Pin;
?GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
?GPIO_InitStruct.Pull = GPIO_NOPULL;
?GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
?HAL_GPIO_Init(LED_GPIO_PC13_GPIO_Port, &GPIO_InitStruct);
?/*Configure GPIO pin : PtPin */
?GPIO_InitStruct.Pin = KEY1_GPIO_PB2_Pin;
?GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
?GPIO_InitStruct.Pull = GPIO_PULLUP;
?HAL_GPIO_Init(KEY1_GPIO_PB2_GPIO_Port, &GPIO_InitStruct);
?/*Configure GPIO pin : PtPin */
?GPIO_InitStruct.Pin = KEY2_EXTI_PB3_Pin;
?GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
?GPIO_InitStruct.Pull = GPIO_PULLUP;
?HAL_GPIO_Init(KEY2_EXTI_PB3_GPIO_Port, &GPIO_InitStruct);
?/* EXTI interrupt init*/
?HAL_NVIC_SetPriority(EXTI3_IRQn, 0, 0);
?HAL_NVIC_EnableIRQ(EXTI3_IRQn);
}
注2 中断处理函数
void EXTI3_IRQHandler(void)
{
?/* USER CODE BEGIN EXTI3_IRQn 0 */
?/* USER CODE END EXTI3_IRQn 0 */
?HAL_GPIO_EXTI_IRQHandler(KEY2_EXTI_PB3_Pin);
?/* USER CODE BEGIN EXTI3_IRQn 1 */
//change LED mode
HAL_GPIO_TogglePin(LED_GPIO_PC13_GPIO_Port, LED_GPIO_PC13_Pin);
?/* USER CODE END EXTI3_IRQn 1 */
}
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
?/* EXTI line interrupt detected */
?if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
?{
? ?__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
? ?HAL_GPIO_EXTI_Callback(GPIO_Pin);
?}
}
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
?/* Prevent unused argument(s) compilation warning */
?UNUSED(GPIO_Pin);
?/* NOTE: This function should not be modified, when the callback is needed,
? ? ? ? ? the HAL_GPIO_EXTI_Callback could be implemented in the user file
? */
}
注3 main函数
int main(void)
{
?/* USER CODE BEGIN 1 */
?/* USER CODE END 1 */
?/* MCU Configuration--------------------------------------------------------*/
?/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
?HAL_Init();
?/* USER CODE BEGIN Init */
?/* USER CODE END Init */
?/* Configure the system clock */
?SystemClock_Config();
?/* USER CODE BEGIN SysInit */
?/* USER CODE END SysInit */
?/* Initialize all configured peripherals */
?MX_GPIO_Init();
?/* USER CODE BEGIN 2 */
?/* USER CODE END 2 */
?/* Infinite loop */
?/* USER CODE BEGIN WHILE */
?while (1)
?{
? ?/* USER CODE END WHILE */
? ?/* USER CODE BEGIN 3 */
/* ?
? ?PC13_LED_Change(LED_ON);
? ?HAL_Delay(500);
? ?PC13_LED_Change(LED_OFF);
? ?HAL_Delay(500); */
? ?if (HAL_GPIO_ReadPin(KEY1_GPIO_PB2_GPIO_Port,KEY1_GPIO_PB2_Pin) == RESET)
? ?{
? ? ?HAL_Delay(5);
? ? ?if (HAL_GPIO_ReadPin(KEY1_GPIO_PB2_GPIO_Port,KEY1_GPIO_PB2_Pin) == RESET)
? ? ?{
? ? ? ?HAL_GPIO_TogglePin(LED_GPIO_PC13_GPIO_Port, LED_GPIO_PC13_Pin);
? ? ?}
? ?}
? ? ?
?}
?/* USER CODE END 3 */
}
注4 LED和KEY1/KEY2的部分原理图
|