Various data types of SPI, UART, I2C and other methods of communication transmission and easy implementation of storage to EEPROM, Flash and other devices

Various types of data transmission and storage involve big and small endian issues. First, let’s briefly talk about the big and small endian issues of the chip. We mainly discuss the Cortex-M core here.
insert image description here

The M kernel supports big-endian or little-endian, and most kernels in practical applications are little-endian. Taking STM32 as an example, all of them are small-endian, and they are solidified at the beginning of chip design and cannot be modified . Other manufacturers on the market basically also solidify the little-endian format.

F1 Programming Manual

F3 and F4 Programming Manual

F7 and H7 Programming Manual

A simple method for programming EEPROM, SPI Flash and other memories of various data types. Generally, these memories are byte-programmed, and it is not convenient to write data types such as floating point. Here is a method to share, define a structure, and encapsulate various data types:


When writing, use the following method:


The following methods can be used to read:


SPI, UART, I2C, etc. transmission issues of various data types. Here we take serial port communication as an example, for example, the host wants to send data in the following format to the slave:

We can make a structure format like this:

typedef struct
{
    
    
    uint8_t ucStart;                        

    uint16_t usCO2;
    uint16_t usPM25;        
    uint16_t usHumidity;          
    float    Temprature;
    uint32_t ulParam;
    uint8_t  ucEnd1;           
    uint8_t  ucEnd2;   
}
UART_T;

UART_T g_tUartParam;

When the host sends, we can use the following methods:

comSendBuf(COM1, (uint8_t *)&g_tUartParam, sizeof(UART_T));

The slave project also defines the same structure variable, for example, we store the received frame of data in the buffer uint8_t buf[50].

We can define a structure pointer variable:

UART_T *pUartParam;
pUartParam = (UART_T *)buf;

Then we can access it in other ways, which is very convenient pUartParam->usCO2.pUartParam->Temprature

Code

The structure data is as follows:

typedef struct
{
    
    
    uint8_t ucStart;                        
 
    uint16_t usCO2;
    uint16_t usPM25;        
    uint16_t usHumidity;         
    float    Temprature;
    uint32_t ulParam;
    uint8_t  ucEnd1;           
    uint8_t  ucEnd2;   
}
USART_T;
 
USART_T g_tUartParam; /* 串口1发送数据使用 */
USART_T *pUartParam;  /* 串口2接数据使用 */
uint8_t buf[128];     /* 接收记录缓冲 */

Data sending and receiving processing:

/*
*********************************************************************************************************
*        函 数 名: main
*        功能说明: c程序入口
*        形    参: 无
*        返 回 值: 错误代码(无需处理)
*********************************************************************************************************
*/
int main(void)
{
    
    
        uint8_t ucKeyCode;        
        uint8_t read;
        uint8_t ucStatus = 0;  /* 状态机标志 */
        uint8_t ucCount=0;
        float ftest = 0.11f;
        pUartParam = (USART_T *)buf;
         
         
        bsp_Init();                /* 硬件初始化 */
         
        PrintfLogo();        /* 打印例程名称和版本等信息 */
        PrintfHelp();        /* 打印操作提示 */
 
 
        bsp_StartAutoTimer(0, 100); /* 启动1个100ms的自动重装的定时器 */
         
        memset(buf, 0, 128);
         
        /* 进入主程序循环体 */
        while (1)
        {
    
    
                bsp_Idle();                /* 这个函数在bsp.c文件。用户可以修改这个函数实现CPU休眠和喂狗 */
 
                /* 判断定时器超时时间 */
                if (bsp_CheckTimer(0))        
                {
    
    
                        /* 每隔100ms 进来一次 */ 
                        bsp_LedToggle(2);                        
                }
                 
                /* 按键滤波和检测由后台systick中断服务程序实现,我们只需要调用bsp_GetKey读取键值即可。 */
                ucKeyCode = bsp_GetKey();        /* 读取键值, 无键按下时返回 KEY_NONE = 0 */
                if (ucKeyCode != KEY_NONE)
                {
    
    
                        switch (ucKeyCode)
                        {
    
    
                                case KEY_DOWN_K1:                        /* K1键按下,串口1发送数据给串口2 */
                                        g_tUartParam.ucStart = '$';
                                        g_tUartParam.usCO2 = 1;
                                        g_tUartParam.usPM25 = 2;
                                        g_tUartParam.usHumidity = 3;
                                        g_tUartParam.Temprature = ftest++;
                                        g_tUartParam.ulParam = 5;        
                                        g_tUartParam.ucEnd1 = '\r';        
                                        g_tUartParam.ucEnd2 = '\n';
                                        comSendBuf(COM1, (uint8_t *)&g_tUartParam, sizeof(UART_T));
                                        printf("发送数据完成\r\n");
                                        break;
 
                                default:
                                        /* 其它的键值不处理 */
                                        break;
                        }
                }
                 
                /* 串口2接收数据解析处理 */
                if (comGetChar(COM2, &read))
                {
    
    
                        switch (ucStatus)
                        {
    
    
                                /* 状态0保证接收到0x01 */
                                case 0:
                                        if(read == '$')
                                        {
    
    
                                                ucStatus = 1; 
                                                buf[ucCount++] = read;
                                        }
                                        break;
 
                                case 1:
                                        buf[ucCount] = read;
                                    
                                        /* 接收够15个数据 */
                                        if((buf[ucCount-1] == '\r')&&(buf[ucCount] == '\n'))
                                        {
    
    
                                                /* 打印接收到的数据值 */
                                                printf("接收到的数据:\r\n");
                                                printf("pUartParam->usCO2 = %d\r\n", pUartParam->usCO2);
                                                printf("pUartParam->usPM25 = %d\r\n", pUartParam->usPM25);
                                                printf("pUartParam->usHumidity = %d\r\n", pUartParam->usHumidity);
                                                printf("pUartParam->Temprature = %f\r\n", pUartParam->Temprature);
                                                printf("pUartParam->ulParam = %d\r\n", pUartParam->ulParam);                                                
                                                printf("\r\n");
                                                 
                                                memset(buf, 0, 128);
                                                ucStatus = 0;
                                                ucCount=0;
                                        }
                                        else
                                        {
    
    
                                                ucCount++;
                                        }
                                        break;
                                 
                                default:
                                        break;
                        }
                }
        }
}

Test effect

Guess you like

Origin blog.csdn.net/qq_39400113/article/details/128263904