文章目录
前言
前面我们学习了定时器,并且用定时器实现1s的LED灯翻转,大家可以回头看一下
用定时器实现1s的LED灯翻转
今天还是用定时器设置一个交通灯!原理还是一样的。
一、GPIO口输出+定时器实验
1、目的
1.熟悉keil和STM32CubeMX的使用,及下载程序方法。
2.学习STM32F407的GPIO口的输出、定时及中断的使用
2、内容
完成交通灯控制,实现东、南、西、北四个方向的交通灯控制,自主定义东、西、南、北方向灯。要求实现如下状态切换:
实验中涉及到的硬件电路见前章内容,按照建议电路连线后,PC0-PC3 控制F6区的DS1-DS4的绿灯部分;PC4-PC7 控制F6区的DS1-DS4的红灯部分。共使用到4组灯。
二、思路
1.STM32CubeMX把IO口使能
用到了PC口,所以在STM32CubeMX配置的时候记得配置PC0~PC7,当然。SYS,RCC,时钟树大家千万不要忘记了,这就是STM32CubeMX的方便之处,在电亮LED的时候
为了便于记忆,可以对IO添加标签,便于记忆
2.对相应引脚进行写操作
可以设置1s的定时器,进行定时
0~5秒执行第一个状态
5~7秒执行第二个状态
7~12秒执行第三个状态
12~15秒执行第四个状态
有人说0——14不就是15个数么,是15个数,但是只有14秒,14个时间间隔。所以要数到15
所以定时器我们可以配置成1S
定时器2的时钟是84M,所以分成8400,就是100kHz,然后再数到10000,那就是1s.
3.使能溢出中断
就是数完了就进一次中断,把中断的事情做完。中断就是发生了更紧急的事,需要CPU立即去解决。
三、Keil编程
生成代码
3.1添加回调函数
在main.c文件添加回调函数,回调函数就相当于中断服务函数,它会指向中断服务函数
3.2 编写用户函数
根据我们的状态转换来编写我们的用户函数,完成相应的功能。
用到了IO口的写函数。
void traffic(void)
{
if(i<5)
{
HAL_GPIO_WritePin(R1_GPIO_Port,R1_Pin,GPIO_PIN_RESET);//东方向红灯亮
HAL_GPIO_WritePin(R2_GPIO_Port,R2_Pin,GPIO_PIN_RESET);//西方向红灯亮
HAL_GPIO_WritePin(G2_GPIO_Port,G2_Pin,GPIO_PIN_RESET);//南方向绿灯亮
HAL_GPIO_WritePin(G3_GPIO_Port,G3_Pin,GPIO_PIN_RESET);//北方向绿灯亮
HAL_GPIO_WritePin(G0_GPIO_Port,G0_Pin,GPIO_PIN_SET);//东方向绿灯不亮
HAL_GPIO_WritePin(G1_GPIO_Port,G1_Pin,GPIO_PIN_SET);//西方向绿灯不亮
HAL_GPIO_WritePin(R3_GPIO_Port,R3_Pin,GPIO_PIN_SET);//南方向红灯不亮
HAL_GPIO_WritePin(R4_GPIO_Port,R4_Pin,GPIO_PIN_SET);//北方向红灯不亮
}
else if(i>=5&&i<7)
{
HAL_GPIO_WritePin(R1_GPIO_Port,R1_Pin,GPIO_PIN_RESET);//东方向红灯亮
HAL_GPIO_WritePin(R2_GPIO_Port,R2_Pin,GPIO_PIN_RESET);//西方向红灯亮
HAL_GPIO_WritePin(G0_GPIO_Port,G0_Pin,GPIO_PIN_RESET);//东方向绿灯亮
HAL_GPIO_WritePin(G1_GPIO_Port,G1_Pin,GPIO_PIN_RESET);//西方向绿灯亮
HAL_GPIO_WritePin(R3_GPIO_Port,R3_Pin,GPIO_PIN_RESET);//南方向红灯亮
HAL_GPIO_WritePin(R4_GPIO_Port,R4_Pin,GPIO_PIN_RESET);//北方向红灯亮
HAL_GPIO_WritePin(G2_GPIO_Port,G2_Pin,GPIO_PIN_RESET);//南方向绿灯亮
HAL_GPIO_WritePin(G3_GPIO_Port,G3_Pin,GPIO_PIN_RESET);//北方向绿灯亮
}
else if(i>=7&i<12)
{
HAL_GPIO_WritePin(G0_GPIO_Port,G0_Pin,GPIO_PIN_RESET);//东方向绿灯亮
HAL_GPIO_WritePin(G1_GPIO_Port,G1_Pin,GPIO_PIN_RESET);//西方向绿灯亮
HAL_GPIO_WritePin(R3_GPIO_Port,R3_Pin,GPIO_PIN_RESET);//南方向红灯亮
HAL_GPIO_WritePin(R4_GPIO_Port,R4_Pin,GPIO_PIN_RESET);//北方向红灯亮
HAL_GPIO_WritePin(R1_GPIO_Port,R1_Pin,GPIO_PIN_SET);//东方向红灯不亮
HAL_GPIO_WritePin(R2_GPIO_Port,R2_Pin,GPIO_PIN_SET);//西方向红灯不亮
HAL_GPIO_WritePin(G2_GPIO_Port,G2_Pin,GPIO_PIN_SET);//南方向绿灯不亮
HAL_GPIO_WritePin(G3_GPIO_Port,G3_Pin,GPIO_PIN_SET);//北方向绿灯不亮
}
else if(i>=12&&i<15)
{
HAL_GPIO_WritePin(R1_GPIO_Port,R1_Pin,GPIO_PIN_RESET);//东方向红灯亮
HAL_GPIO_WritePin(R2_GPIO_Port,R2_Pin,GPIO_PIN_RESET);//西方向红灯亮
HAL_GPIO_WritePin(G0_GPIO_Port,G0_Pin,GPIO_PIN_RESET);//东方向绿灯亮
HAL_GPIO_WritePin(G1_GPIO_Port,G1_Pin,GPIO_PIN_RESET);//西方向绿灯亮
HAL_GPIO_WritePin(R3_GPIO_Port,R3_Pin,GPIO_PIN_RESET);//南方向红灯亮
HAL_GPIO_WritePin(R4_GPIO_Port,R4_Pin,GPIO_PIN_RESET);//北方向红灯亮
HAL_GPIO_WritePin(G2_GPIO_Port,G2_Pin,GPIO_PIN_RESET);//南方向绿灯亮
HAL_GPIO_WritePin(G3_GPIO_Port,G3_Pin,GPIO_PIN_RESET);//北方向绿灯亮
}
}
3.3主函数调用
在main.c里面添加定时器启动语句
完整main.c文件
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
uint8_t i;
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim == &htim2)
{
i++;
if(i>=15)
{
i=0;
}
}
}
void traffic(void)
{
if(i<5)
{
HAL_GPIO_WritePin(R1_GPIO_Port,R1_Pin,GPIO_PIN_RESET);//东方向红灯亮
HAL_GPIO_WritePin(R2_GPIO_Port,R2_Pin,GPIO_PIN_RESET);//西方向红灯亮
HAL_GPIO_WritePin(G2_GPIO_Port,G2_Pin,GPIO_PIN_RESET);//南方向绿灯亮
HAL_GPIO_WritePin(G3_GPIO_Port,G3_Pin,GPIO_PIN_RESET);//北方向绿灯亮
HAL_GPIO_WritePin(G0_GPIO_Port,G0_Pin,GPIO_PIN_SET);//东方向绿灯不亮
HAL_GPIO_WritePin(G1_GPIO_Port,G1_Pin,GPIO_PIN_SET);//西方向绿灯不亮
HAL_GPIO_WritePin(R3_GPIO_Port,R3_Pin,GPIO_PIN_SET);//南方向红灯不亮
HAL_GPIO_WritePin(R4_GPIO_Port,R4_Pin,GPIO_PIN_SET);//北方向红灯不亮
}
else if(i>=5&&i<7)
{
HAL_GPIO_WritePin(R1_GPIO_Port,R1_Pin,GPIO_PIN_RESET);//东方向红灯亮
HAL_GPIO_WritePin(R2_GPIO_Port,R2_Pin,GPIO_PIN_RESET);//西方向红灯亮
HAL_GPIO_WritePin(G0_GPIO_Port,G0_Pin,GPIO_PIN_RESET);//东方向绿灯亮
HAL_GPIO_WritePin(G1_GPIO_Port,G1_Pin,GPIO_PIN_RESET);//西方向绿灯亮
HAL_GPIO_WritePin(R3_GPIO_Port,R3_Pin,GPIO_PIN_RESET);//南方向红灯亮
HAL_GPIO_WritePin(R4_GPIO_Port,R4_Pin,GPIO_PIN_RESET);//北方向红灯亮
HAL_GPIO_WritePin(G2_GPIO_Port,G2_Pin,GPIO_PIN_RESET);//南方向绿灯亮
HAL_GPIO_WritePin(G3_GPIO_Port,G3_Pin,GPIO_PIN_RESET);//北方向绿灯亮
}
else if(i>=7&i<12)
{
HAL_GPIO_WritePin(G0_GPIO_Port,G0_Pin,GPIO_PIN_RESET);//东方向绿灯亮
HAL_GPIO_WritePin(G1_GPIO_Port,G1_Pin,GPIO_PIN_RESET);//西方向绿灯亮
HAL_GPIO_WritePin(R3_GPIO_Port,R3_Pin,GPIO_PIN_RESET);//南方向红灯亮
HAL_GPIO_WritePin(R4_GPIO_Port,R4_Pin,GPIO_PIN_RESET);//北方向红灯亮
HAL_GPIO_WritePin(R1_GPIO_Port,R1_Pin,GPIO_PIN_SET);//东方向红灯不亮
HAL_GPIO_WritePin(R2_GPIO_Port,R2_Pin,GPIO_PIN_SET);//西方向红灯不亮
HAL_GPIO_WritePin(G2_GPIO_Port,G2_Pin,GPIO_PIN_SET);//南方向绿灯不亮
HAL_GPIO_WritePin(G3_GPIO_Port,G3_Pin,GPIO_PIN_SET);//北方向绿灯不亮
}
else if(i>=12&&i<15)
{
HAL_GPIO_WritePin(R1_GPIO_Port,R1_Pin,GPIO_PIN_RESET);//东方向红灯亮
HAL_GPIO_WritePin(R2_GPIO_Port,R2_Pin,GPIO_PIN_RESET);//西方向红灯亮
HAL_GPIO_WritePin(G0_GPIO_Port,G0_Pin,GPIO_PIN_RESET);//东方向绿灯亮
HAL_GPIO_WritePin(G1_GPIO_Port,G1_Pin,GPIO_PIN_RESET);//西方向绿灯亮
HAL_GPIO_WritePin(R3_GPIO_Port,R3_Pin,GPIO_PIN_RESET);//南方向红灯亮
HAL_GPIO_WritePin(R4_GPIO_Port,R4_Pin,GPIO_PIN_RESET);//北方向红灯亮
HAL_GPIO_WritePin(G2_GPIO_Port,G2_Pin,GPIO_PIN_RESET);//南方向绿灯亮
HAL_GPIO_WritePin(G3_GPIO_Port,G3_Pin,GPIO_PIN_RESET);//北方向绿灯亮
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
//增加Time2启动语句
HAL_TIM_Base_Start_IT(&htim2); //允许定时器TIM2中断,使能TIM2开始工作
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
traffic();
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
总结
代码都是调出来和改出来的,慢慢积累和进步~,学32就得学会举一反三。