写一个STM32L051C8T6的代码,使用HAL库,使用内部EEPROM存储,要求上电发送“0000”,回复进入地址设置指令,进入地址设定状态,保证7个RGBLED灭,然后在对应地址放入瓶子,轮询三次,相应的RGBLED闪三下,LED闪三下一样的绿色则最后显示绿灯,LED闪三下不同的(绿色或红色)则最后显示红灯,显示绿灯则串口1显示正确的地址,显示红灯则不显,当地址设定正确后,地址设定状态结束,进入工作状态
时间: 2023-10-23 14:10:45 浏览: 81
好的,根据您的要求,我已经编写出一份基于HAL库的STM32L051C8T6代码,并在注释中详细说明了各个步骤的实现方法,供您参考。
```c
#include "stm32l0xx_hal.h"
// 定义串口句柄
UART_HandleTypeDef huart1;
// 定义EEPROM存储地址和大小
#define EEPROM_START_ADDR ((uint32_t)0x08080000)
#define EEPROM_SIZE ((uint32_t)0x400)
// 定义RGB灯的引脚
#define LED_R_PIN GPIO_PIN_0
#define LED_G_PIN GPIO_PIN_1
#define LED_B_PIN GPIO_PIN_2
#define LED_PORT GPIOA
// 定义地址设定状态和工作状态的状态变量
#define STATE_ADDR_SETTING 0
#define STATE_WORKING 1
uint8_t state = STATE_ADDR_SETTING;
// 定义瓶子的地址变量
uint8_t bottle_addr = 0;
// 定义三个RGB灯的状态变量
uint8_t led_r_state = 0;
uint8_t led_g_state = 0;
uint8_t led_b_state = 0;
// 定义RGB灯亮的时间和灭的时间
#define LED_ON_TIME 100
#define LED_OFF_TIME 100
// 定义轮询瓶子的次数
#define POLL_COUNT 3
// 声明函数
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_FLASH_Init(void);
static void EEPROM_WriteByte(uint32_t addr, uint8_t data);
static uint8_t EEPROM_ReadByte(uint32_t addr);
int main(void)
{
// 初始化HAL库
HAL_Init();
// 配置系统时钟
SystemClock_Config();
// 初始化GPIO
MX_GPIO_Init();
// 初始化USART1
MX_USART1_UART_Init();
// 初始化FLASH
MX_FLASH_Init();
// 在上电时发送“0000”
HAL_UART_Transmit(&huart1, (uint8_t *)"0000\r\n", 6, HAL_MAX_DELAY);
// 进入地址设置状态
state = STATE_ADDR_SETTING;
// 使7个RGB灯熄灭
HAL_GPIO_WritePin(LED_PORT, LED_R_PIN | LED_G_PIN | LED_B_PIN, GPIO_PIN_RESET);
// 轮询瓶子三次
uint8_t led_r_count = 0;
uint8_t led_g_count = 0;
uint8_t led_b_count = 0;
for (uint8_t i = 0; i < POLL_COUNT; i++) {
// 读取当前地址对应的瓶子
uint8_t bottle = EEPROM_ReadByte(EEPROM_START_ADDR + bottle_addr);
// 根据瓶子的颜色控制RGB灯
if (bottle == 0) {
HAL_GPIO_WritePin(LED_PORT, LED_R_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_PORT, LED_G_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_PORT, LED_B_PIN, GPIO_PIN_RESET);
led_g_count++;
} else if (bottle == 1) {
HAL_GPIO_WritePin(LED_PORT, LED_R_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_PORT, LED_G_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_PORT, LED_B_PIN, GPIO_PIN_RESET);
led_r_count++;
} else if (bottle == 2) {
HAL_GPIO_WritePin(LED_PORT, LED_R_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_PORT, LED_G_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_PORT, LED_B_PIN, GPIO_PIN_SET);
led_b_count++;
}
// 等待LED亮的时间
HAL_Delay(LED_ON_TIME);
// 关闭RGB灯
HAL_GPIO_WritePin(LED_PORT, LED_R_PIN | LED_G_PIN | LED_B_PIN, GPIO_PIN_RESET);
// 等待LED灭的时间
HAL_Delay(LED_OFF_TIME);
}
// 根据亮的次数判断显示什么颜色的灯
if (led_r_count == POLL_COUNT) {
HAL_GPIO_WritePin(LED_PORT, LED_R_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_PORT, LED_G_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_PORT, LED_B_PIN, GPIO_PIN_RESET);
// 显示地址
if (state == STATE_WORKING) {
HAL_UART_Transmit(&huart1, &bottle_addr, 1, HAL_MAX_DELAY);
}
} else if (led_g_count == POLL_COUNT) {
HAL_GPIO_WritePin(LED_PORT, LED_R_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_PORT, LED_G_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_PORT, LED_B_PIN, GPIO_PIN_RESET);
} else {
HAL_GPIO_WritePin(LED_PORT, LED_R_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_PORT, LED_G_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_PORT, LED_B_PIN, GPIO_PIN_SET);
}
// 进入工作状态
state = STATE_WORKING;
while (1)
{
// 读取串口接收到的数据
uint8_t data;
HAL_UART_Receive(&huart1, &data, 1, HAL_MAX_DELAY);
// 如果接收到进入地址设置状态的指令,则进入地址设置状态
if (state == STATE_WORKING && data == 'A') {
state = STATE_ADDR_SETTING;
HAL_GPIO_WritePin(LED_PORT, LED_R_PIN | LED_G_PIN | LED_B_PIN, GPIO_PIN_RESET);
continue;
}
// 如果当前是地址设置状态,则将接收到的数据作为地址值
if (state == STATE_ADDR_SETTING) {
bottle_addr = data;
continue;
}
// 如果当前是工作状态,则将接收到的数据作为瓶子颜色放入对应的地址
if (state == STATE_WORKING) {
EEPROM_WriteByte(EEPROM_START_ADDR + bottle_addr, data);
continue;
}
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_PORT, LED_R_PIN | LED_G_PIN | LED_B_PIN, GPIO_PIN_RESET);
/*Configure GPIO pins : LED_R_PIN LED_G_PIN LED_B_PIN */
GPIO_InitStruct.Pin = LED_R_PIN | LED_G_PIN | LED_B_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
}
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONEBIT_SAMPLING_DISABLED;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
static void MX_FLASH_Init(void)
{
/* USER CODE BEGIN FLASH_Init 0 */
/* USER CODE END FLASH_Init 0 */
/* USER CODE BEGIN FLASH_Init 1 */
/* USER CODE END FLASH_Init 1 */
HAL_FLASH_Unlock();
/* USER CODE BEGIN FLASH_Init 2 */
/* USER CODE END FLASH_Init 2 */
HAL_FLASH_Lock();
}
void EEPROM_WriteByte(uint32_t addr, uint8_t data)
{
// 等待上一个操作完成
while (FLASH->SR & FLASH_SR_BSY);
// 解锁FLASH
HAL_FLASH_Unlock();
// 擦除要写入的地址所在的扇区
FLASH_EraseInitTypeDef erase_init = {0};
erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
erase_init.PageAddress = addr;
erase_init.NbPages = 1;
uint32_t page_error;
HAL_FLASHEx_Erase(&erase_init, &page_error);
// 写入数据
HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, addr, data);
// 加锁FLASH
HAL_FLASH_Lock();
}
uint8_t EEPROM_ReadByte(uint32_t addr)
{
return *(uint8_t *)addr;
}
```
需要注意的是,这份代码并没有完全测试过,可能存在一些bug或需要调整的地方,但是它可以作为您开始实现这个项目的一个参考。
阅读全文