- void eeprom_I2C_Configure(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- I2C_InitTypeDef I2C_InitStruct;
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
- I2C_DeInit(I2C1);
- I2C_StructInit(&I2C_InitStruct);
- I2C_InitStruct.I2C_Mode = I2C_MODE_MASTER;
- I2C_InitStruct.I2C_OwnAddress = I2C_OWN_ADDRESS;
- I2C_InitStruct.I2C_ClockSpeed = 100000;
- I2C_Init(I2C1, &I2C_InitStruct);
- I2C_TargetAddressConfig(I2C1, EEPROM_I2C_ADDRESS);
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
- GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_1);
- GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_1);
- GPIO_StructInit(&GPIO_InitStruct);
- GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
- GPIO_Init(GPIOB, &GPIO_InitStruct);
- I2C_Cmd(I2C1, ENABLE);
- }
I2C写数据
- void I2C_TxData_Polling(uint8_t *Buffer, uint8_t Length)
- {
- uint8_t i = 0;
- for (i = 0; i < Length; i++)
- {
- I2C_SendData(I2C1, Buffer[i]);
- while (RESET == I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE))
- {
- }
- }
- }
I2C读数据
- void I2C_RxData_Polling(uint8_t *Buffer, uint16_t Length)
- {
- uint8_t i = 0;
- for (i = 0; i < Length; i++)
- {
- I2C_ReadCmd(I2C1);
- while (RESET == I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_RFNE))
- {
- }
- Buffer[i] = I2C_ReceiveData(I2C1);
- }
- }
EEPROM写页函数
- void EEPROM_WritePage(uint8_t Address, uint8_t *Buffer, uint8_t Length)
- {
- I2C_TxData_Polling((uint8_t *)&Address, 0x01);
- I2C_TxData_Polling((uint8_t *)Buffer, Length);
- while (RESET == I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE))
- {
- }
- I2C_GenerateSTOP(I2C1);
- while (RESET == I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE))
- {
- }
- }
EEPROM读数据函数
- void EEPROM_ReadData(uint8_t Address, uint8_t *Buffer, uint8_t Length)
- {
- I2C_TxData_Polling((uint8_t *)&Address, 0x01);
- I2C_RxData_Polling((uint8_t *)Buffer, Length);
- I2C_GenerateSTOP(I2C1);
- while (RESET == I2C_GetFlagStatus(I2C1, I2C_STATUS_FLAG_TFE))
- {
- }
- }
EEPROM写数据函数
- void EEPROM_WriteData(uint8_t Address, uint8_t *Buffer, uint8_t Length)
- {
- uint8_t Start = 0;
- uint8_t StartCount = 0, PageNumber = 0, FinalCount = 0;
- if ((Address % EEPROM_PAGE_SIZE) == 0)
- {
- StartCount = 0;
- PageNumber = Length / EEPROM_PAGE_SIZE;
- FinalCount = Length % EEPROM_PAGE_SIZE;
- }
- else
- {
- Start = Address % EEPROM_PAGE_SIZE;
- if (((Start + Length) / EEPROM_PAGE_SIZE) == 0)
- {
- StartCount = Length;
- PageNumber = 0;
- FinalCount = 0;
- }
- else
- {
- StartCount = EEPROM_PAGE_SIZE - Start;
- PageNumber = (Length - StartCount) / EEPROM_PAGE_SIZE;
- FinalCount = (Length - StartCount) % EEPROM_PAGE_SIZE;
- }
- }
- if (StartCount)
- {
- EEPROM_WritePage(Address, Buffer, StartCount);
- Address += StartCount;
- Buffer += StartCount;
- PLATFORM_DelayMS(50);
- }
- while (PageNumber--)
- {
- EEPROM_WritePage(Address, Buffer, EEPROM_PAGE_SIZE);
- Address += EEPROM_PAGE_SIZE;
- Buffer += EEPROM_PAGE_SIZE;
- PLATFORM_DelayMS(50);
- }
- if (FinalCount)
- {
- EEPROM_WritePage(Address, Buffer, FinalCount);
- }
- }
二、json数据处理
数据格式定义:
+--------+--------+-------------------+--------+
| 长度H | 长度L | JSON原始数据 | 校验位|
| (1B) | (1B) | (N字节) | (1B) |
+--------+--------+-------------------+--------+
有效的数据示例:{"device":"MM32F0120","version":1.12,"enable":1}
save_config_to_eeprom()生成初始的json数据保存到EEPROM中
- //JSON数据格式化存储
- void save_config_to_eeprom(void) {
- // 1. 创建JSON对象
- cJSON *root = cJSON_CreateObject();
- cJSON_AddStringToObject(root, "device", "MM32F0120");
- cJSON_AddNumberToObject(root, "version", 1.12);
- cJSON_AddBoolToObject(root, "enable", true);
-
- // 2. 序列化为字符串
- char *json_str = cJSON_PrintUnformatted(root);
- uint16_t json_len = strlen(json_str);
-
- // 3. 添加长度头(2字节)和数据校验(1字节)
- uint8_t *buffer = malloc(json_len + 3);
- buffer[0] = json_len >> 8; // 长度高字节
- buffer[1] = json_len & 0xFF; // 长度低字节
-
- // 计算简单校验和
- uint8_t checksum = 0;
- for(int i=0; i<json_len; i++) {
- buffer[i+2] = json_str[i];
- checksum ^= json_str[i]; // XOR校验
- }
- buffer[json_len+2] = checksum;
-
- // 4. 写入EEPROM
- EEPROM_WriteData(JSON_START_ADDR, buffer, json_len+3);
-
- // 5. 释放资源
- free(buffer);
- free(json_str);
- cJSON_Delete(root);
- }
load_config_from_eeprom()从EEPROM读取JSON数据
- //从EEPROM读取JSON数据
- cJSON* load_config_from_eeprom(void) {
- // 1. 读取长度头
- uint8_t len_buf[2];
- EEPROM_ReadData(JSON_START_ADDR, len_buf, 2);
- uint16_t json_len = (len_buf[0] << 8) | len_buf[1];
-
- // 2. 读取JSON数据和校验位
- uint8_t *buffer = malloc(json_len + 1);
- EEPROM_ReadData(JSON_START_ADDR+2, buffer, json_len+1);
- printf("%s\r\n",buffer);
-
- // 3. 校验数据
- uint8_t checksum = 0;
- for(int i=0; i<json_len; i++) {
- checksum ^= buffer[i];
- }
-
- if(checksum != buffer[json_len]) {
- free(buffer);
- return NULL; // 校验失败
- }
-
- // 4. 解析JSON
- buffer[json_len] = '\0'; // 添加字符串结束符
- cJSON *root = cJSON_Parse((char*)buffer);
-
- free(buffer);
- return root;
- }
通过以上实现了向EEPROM写JSON数据和读取数据,可以通过以下程序验证:
- void eeprom_Sample(void)
- {
- eeprom_I2C_Configure()
- save_config_to_eeprom();
- PLATFORM_DelayMS(500);
- // 读取配置
- cJSON *config = load_config_from_eeprom();
- if(config) {
- cJSON *device = cJSON_GetObjectItem(config, "device");
- cJSON *version = cJSON_GetObjectItem(config, "version");
- printf("Device: %s, Ver: %.2f\n", device->valuestring, version->valuedouble);
- cJSON_Delete(config);
- } else {
- printf("Config load failed!\n");
- }
- while(1)
- {
- }
- }
三、接收串口发过来的json数据保存到EEPROM
这里使用了UART不定长数据接收,可参考:https://bbs.21ic.com/icview-3461324-1-1.html
UART输入判断
- static void Process_Uart_Input(void)
- {
- uint8_t frame_data[MAX_JSON_LEN];
- uint8_t i,frame_len;
- if(USART_RxStruct.Buffer[0]=='{'&&USART_RxStruct.Buffer[USART_RxStruct.CurrentCount-3]=='}')
- {
- frame_len=USART_RxStruct.CurrentCount-2;
- for(i = 0; i < frame_len; i++) {
- frame_data[i] = USART_RxStruct.Buffer[i];
- }
- frame_data[frame_len]='\0';
- if(is_json_valid(frame_data, frame_len)) {
- save_json_to_eeprom(frame_data,frame_len);
- }else
- {
- printf("json format is invalid\r\n");
- }
- }
- USART_RxData_Interrupt(255);
- USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
- }
对UART传过来的数据进行JSON格式验证
- // 验证JSON格式
- uint8_t is_json_valid(const uint8_t *data, uint16_t len) {
- // 确保以NULL结尾
- char *json_str = malloc(len + 1);
- if(!json_str) return 0;
-
- memcpy(json_str, data, len);
- json_str[len] = '\0';
- printf("json_str:%s\r\n",json_str);
- // 解析JSON
- cJSON *root = cJSON_Parse(json_str);
- uint8_t result = 0;
-
- if(root) {
- // 验证基本结构
- cJSON *device = cJSON_GetObjectItem(root, "device");
- cJSON *version = cJSON_GetObjectItem(root, "version");
- cJSON *enable = cJSON_GetObjectItem(root, "enable");
- printf("device=%s,version=%s,enable=%s\r\n",device->valuestring,version->valuestring,enable->valuestring);
- if(cJSON_IsString(device) && cJSON_IsNumber(version) &&
- (cJSON_IsNumber(enable) || cJSON_IsBool(enable))) {
- result = 1;
- }
-
- cJSON_Delete(root);
- }
-
- free(json_str);
- return result;
- }
对UART接收的JSON打包,添加长度头和校验
- // 封装JSON数据(添加长度头和校验)
- uint16_t package_json(const uint8_t *json, uint16_t json_len, uint8_t *output) {
- if(json_len > MAX_JSON_LEN) return 0;
-
- // 添加长度头(小端格式)
- output[0] = (json_len >> 8) & 0xFF; // 高字节
- output[1] = json_len & 0xFF; // 低字节
-
- // 复制JSON数据
- memcpy(&output[2], json, json_len);
-
- // 计算并添加校验位(异或校验)
- uint8_t checksum = 0;
- for(uint16_t i = 0; i < json_len; i++) {
- checksum ^= json[i];
- }
- output[2 + json_len] = checksum;
-
- return json_len + 3; // 总长度 = 2(头) + json_len + 1(校验)
- }
保存JSON到EEPROM
- // 保存JSON到EEPROM
- void save_json_to_eeprom(const uint8_t *json, uint16_t len) {
- // 封装数据
- uint8_t packaged_data[MAX_JSON_LEN + 3];
- uint16_t packaged_len = package_json(json, len, packaged_data);
- printf("packaged_data=%s",packaged_data);
- if(packaged_len > 0) {
- // 写入EEPROM
- EEPROM_WriteData(JSON_START_ADDR, packaged_data, packaged_len);
- printf("JSON saved successfully\n");
- }
- }
写个验证程序
- void eeprom_Sample(void)
- {
- USART_RxStruct.CompleteFlag = 0;
- USART_TxStruct.CompleteFlag = 1;
- USART_Configure(115200);
- eeprom_I2C_Configure();
-
- // 保存配置
- //save_config_to_eeprom();
- PLATFORM_DelayMS(500);
- // 读取配置
- cJSON *config = load_config_from_eeprom();
- if(config) {
- cJSON *device = cJSON_GetObjectItem(config, "device");
- cJSON *version = cJSON_GetObjectItem(config, "version");
- printf("Device: %s, Ver: %.2f\n", device->valuestring, version->valuedouble);
- cJSON_Delete(config);
- } else {
- printf("Config load failed!\n");
- }
-
- while(1)
- {
-
- if (1== USART_RxStruct.CompleteFlag&&USART_RxStruct.CurrentCount>0)
- {
- USART_RxStruct.CompleteFlag=0;
- Process_Uart_Input();
- }
- PLATFORM_LED_Toggle(LED1);
- PLATFORM_LED_Toggle(LED2);
- PLATFORM_DelayMS(100);
- }
- }
1、上电,显示之前保存的json文件内容,其中"version":3.12
2、通过串口发送{"device":"MM32F0120","version":8.88,"enable":true},改变"version"为8.88
3、再次RESET,显示修改后的"version"为8.88