写一个STM32L051C8T6的代码,使用HAL库,使用内部EEPROM存储,要求上电发送进入地址设置指令,进入地址设定状态,保证7个RGBLED灭,然后在对应地址放入瓶子,轮询三次,相应的RGBLED闪三下,LED闪三下一样的绿色则最后显示绿灯,LED闪三下不同的(绿色或红色)则最后显示红灯,显示绿灯则串口1显示正确的地址,显示红灯则不显,当地址设定正确后,地址设定状态结束,进入工作状态,运行其他工作代码
时间: 2023-10-02 19:12:09 浏览: 40
以下是实现上述功能的示例代码,代码中用到了内部EEPROM存储和HAL库:
```c
#include "main.h"
#include "stm32l0xx_hal.h"
#define EEPROM_ADDR 0x08080000 // 内部EEPROM起始地址
#define LED_NUM 7 // LED数量
#define POLL_TIMES 3 // 轮询次数
GPIO_TypeDef* LED_GPIO_Port[LED_NUM] = {GPIOA, GPIOA, GPIOA, GPIOA, GPIOA, GPIOB, GPIOB}; // LED的GPIO端口
uint16_t LED_Pin[LED_NUM] = {GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3, GPIO_PIN_4, GPIO_PIN_2, GPIO_PIN_10}; // LED的GPIO引脚
UART_HandleTypeDef huart1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
// 上电发送进入地址设置指令
uint8_t enter_addr_cmd[4] = {0x7E, 0xFF, 0x06, 0x41};
HAL_UART_Transmit(&huart1, enter_addr_cmd, 4, HAL_MAX_DELAY);
// 进入地址设定状态
uint8_t addr_set[5] = {0x7E, 0xFF, 0x07, 0x41, 0x00};
HAL_UART_Transmit(&huart1, addr_set, 5, HAL_MAX_DELAY);
// 保证7个RGBLED灭
for(int i=0; i<LED_NUM; i++){
HAL_GPIO_WritePin(LED_GPIO_Port[i], LED_Pin[i], GPIO_PIN_RESET);
}
// 在对应地址放入瓶子
uint8_t bottle_addr = 0x01;
HAL_FLASHEx_DATAEEPROM_Unlock(); // 解锁EEPROM
HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EEPROM_ADDR, bottle_addr); // 写入EEPROM
HAL_FLASHEx_DATAEEPROM_Lock(); // 锁定EEPROM
// 轮询三次,相应的RGBLED闪三下
uint8_t led_status[LED_NUM] = {0}; // 记录各个LED的状态
for(int i=0; i<POLL_TIMES; i++){
uint8_t read_addr_cmd[4] = {0x7E, 0xFF, 0x06, 0x42};
HAL_UART_Transmit(&huart1, read_addr_cmd, 4, HAL_MAX_DELAY);
uint8_t read_buf[10] = {0};
HAL_UART_Receive(&huart1, read_buf, 10, HAL_MAX_DELAY);
if(read_buf[3] == 0x42 && read_buf[4] == 0x00){
uint8_t cur_addr = read_buf[5];
if(cur_addr >= 1 && cur_addr <= LED_NUM){
if(!led_status[cur_addr-1]){ // LED第一次闪烁
HAL_GPIO_WritePin(LED_GPIO_Port[cur_addr-1], LED_Pin[cur_addr-1], GPIO_PIN_SET);
led_status[cur_addr-1] = 1;
}
else if(led_status[cur_addr-1] == 1){ // LED第二次闪烁
HAL_GPIO_WritePin(LED_GPIO_Port[cur_addr-1], LED_Pin[cur_addr-1], GPIO_PIN_RESET);
led_status[cur_addr-1] = 2;
}
else{ // LED第三次闪烁
HAL_GPIO_WritePin(LED_GPIO_Port[cur_addr-1], LED_Pin[cur_addr-1], GPIO_PIN_SET);
led_status[cur_addr-1] = 0;
}
}
}
}
// 判断最后的LED状态
int led_count[2] = {0}; // 统计绿色和红色LED的数量
for(int i=0; i<LED_NUM; i++){
if(HAL_GPIO_ReadPin(LED_GPIO_Port[i], LED_Pin[i]) == GPIO_PIN_SET){
if(i < 5){ // 前5个LED为绿色
led_count[0]++;
}
else{ // 后2个LED为红色
led_count[1]++;
}
}
}
// 最后显示绿灯或红灯
if(led_count[1] > 0){ // 显示红灯,不显串口1
HAL_GPIO_WritePin(LED_GPIO_Port[0], LED_Pin[0], GPIO_PIN_SET);
}
else{ // 显示绿灯,串口1显示正确的地址
uint8_t read_addr_cmd[4] = {0x7E, 0xFF, 0x06, 0x42};
HAL_UART_Transmit(&huart1, read_addr_cmd, 4, HAL_MAX_DELAY);
uint8_t read_buf[10] = {0};
HAL_UART_Receive(&huart1, read_buf, 10, HAL_MAX_DELAY);
if(read_buf[3] == 0x42 && read_buf[4] == 0x00){
uint8_t cur_addr = read_buf[5];
char addr_str[20] = {0};
sprintf(addr_str, "Address: %d\r\n", cur_addr);
HAL_UART_Transmit(&huart1, (uint8_t*)addr_str, strlen(addr_str), HAL_MAX_DELAY);
}
HAL_GPIO_WritePin(LED_GPIO_Port[1], LED_Pin[1], GPIO_PIN_SET);
}
// 地址设定状态结束,进入工作状态
uint8_t work_mode[5] = {0x7E, 0xFF, 0x06, 0x41, 0x01};
HAL_UART_Transmit(&huart1, work_mode, 5, HAL_MAX_DELAY);
while (1)
{
// 运行其他工作代码
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure LSE Drive Capability
*/
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
HAL_PWR_DisableBkUpAccess();
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_LSE;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
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;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
// 初始化LED的GPIO端口
for(int i=0; i<LED_NUM; i++){
GPIO_InitStruct.Pin = LED_Pin[i];
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_GPIO_Port[i], &GPIO_InitStruct);
}
}
```