1 驱动层开发
1.1 器件读写接口
嵌入式产品中的器件,如传感器,都需要通过 SPI/I2C 等接口实现配置和功能应用。在不同的开发平台上,SPI/I2C 读写的 API 接口是不一样的。因此,在编写器件驱动程序时,首先会封装出 SPI/I2C 的读写函数,屏蔽掉平台接口的影响。
下面通过几个例子来分享下器件驱动编写时的技巧方法。
案例一 (STM32-I2C)
简单地,在 STM32 平台上的 Max17050 的 I2C 驱动接口可如下所示,这样做的好处
- 经过第一级封装,屏蔽掉了平台的 API 接口及其错误提醒
- 经过第二级封装,屏蔽掉了两个不同器件的 I2C 地址,输入参数聚焦在要写入的寄存器和寄存器值
HAL_StatusTypeDef charger_box_i2c_write_byte_poll(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
HAL_StatusTypeDef state = HAL_OK;
state = HAL_I2C_Mem_Write(hi2c, DevAddress, MemAddress, MemAddSize, pData, Size, Timeout);
if(state != HAL_OK)
{
I2C_ERROR_Handler(hi2c);
}
return state;
}
HAL_StatusTypeDef bsp_ir_driver_pa2240_write_register(IR_ID_E ir_id, uint8_t register_addr, uint8_t register_value)
{
if(ir_id == IR_ID_LEFT)
{
return charger_box_i2c_write_byte_poll(&hi2c1, PA22A_I2C_ADDRESS, register_addr, 1, ®ister_value, 1, 1000);
}
else if( ir_id == IR_ID_RIGHT)
{
return charger_box_i2c_write_byte_poll(&hi2c2, PA22A_I2C_ADDRESS, register_addr, 1, ®ister_value, 1, 1000);
}
else
{
return HAL_ERROR;
}
}
案例二 (Nordic-I2C)
STM32 I2C 读写 API 中,器件地址,寄存器地址和寄存器值是分开的,但在其他平台中,要求寄存器地址和寄存器值合并在一起作为写入数据,如 Nordic 平台。
此时有两种处理方法,一种是寄存器地址和寄存器值分别调用一条 API 写入,另一是将寄存器地址和寄存器值合并后调用一条 API 写入。
static int32_t platform_write(void *handle, uint8_t reg, uint8_t *pbuf,
uint16_t len)
{
nrf_drv_twi_tx(handle, LIS2DW12_ADDR, ®, 1, false); // 发送寄存器地址
nrf_drv_twi_tx(handle, LIS2DW12_ADDR, pbuf, len, false); // 发送寄存器值
return 0;
}
static uint8_t Txbuff[10];
static volatile bool twi_xfer_done = false;
static int32_t platform_write(void *handle, uint8_t reg, uint8_t *pbuf,
uint16_t len)
{
Txbuff[0] = reg;
memcpy((Txbuff + 1), pbuf, len);
twi_xfer_done = false;
do{
nrf_drv_twi_tx(handle, LIS2DW12_ADDR, Txbuff, len + 1, false);
}while(!twi_xfer_done);
return 0;
}
案例三 (Cypress-SPI)
相比 I2C 标准协议,采用 SPI 通信的器件对 SPI 发送的数据序列和数据大小可能会有个性化规定,如 MAX86141,要求发送的第一个 byte 为寄存器地址,第二个 byte 为读写模式,第三个 byte 才是寄存器值。
void MAX86141_ReadByte(uint8_t Reg_addr,uint8_t *pBuf , uint8_t Len)
{
uint8_t data_arr[3] = {0};
data_arr[0] = Reg_addr;
data_arr[1] = READ_IC_MODE; //READ =0x80
MAX86141_ENABLE;
wiced_hal_pspi_tx_data(SPI1,2, data_arr);
wiced_hal_pspi_rx_data(SPI1,Len, pBuf);
MAX86141_DISABLE;
}
void MAX86141_WriteByte(uint8_t Reg_addr, uint8_t Data)
{
uint8_t data_arr[3] = {0};
data_arr[0] = Reg_addr;
data_arr[1] = WRITE_IC_MODE;
data_arr[2] = Data;
MAX86141_ENABLE;
wiced_hal_pspi_tx_data(SPI1,3, data_arr);
MAX86141_DISABLE;
}