以ADC芯片SGM51242向大家展示驱动代码的设计理念
本帖最后由 dffzh 于 2025-5-23 11:17 编辑#申请原创#
@21小跑堂
做嵌入式软件开发时,我们会经常编写包括ADC芯片和DAC芯片等在内的驱动代码;那怎么样编写驱动代码才能提高程序调试效率,以及提高驱动代码后续的可维护性和复用率呢?今天作者就通过ADC芯片SGM51242向大家展示驱动代码的设计思路和方法,用到的C语言知识点主要包括宏定义、宏函数、枚举类型和位运算符,希望对大家以后设计和编写驱动代码有所帮助。通用的芯片驱动代码一般包括一个源文件和一个头文件,源文件主要是函数定义,涉及芯片初始化配置、读芯片寄存器(读数据)、写芯片寄存器(写数据)和软复位寄存器等常用操作,头文件主要是宏定义,枚举定义,变量声明和函数声明等。先附上驱动代码的头文件:#ifndef __SGM51242_H__#define __SGM51242_H__
#include "at32f403a_407.h"#include "bsp_spi_bus.h"
#define SGM51242_GPIO GPIOA#define SGM51242_CS_GPIO GPIOA //ADC nSYNC pin#define SGM51242_CLK_GPIO GPIOB#define SGM51242_MOSI_GPIO GPIOB#define SGM51242_MISO_GPIO GPIOB
#define SGM51242_CS_PIN GPIO_PINS_15#define SGM51242_CLK_PIN GPIO_PINS_3#define SGM51242_MOSI_PIN GPIO_PINS_5#define SGM51242_MISO_PIN GPIO_PINS_4
#defineSGM51242_CS_HIGH() gpio_bits_write(SGM51242_CS_GPIO, SGM51242_CS_PIN, TRUE)#defineSGM51242_CS_LOW() gpio_bits_write(SGM51242_CS_GPIO, SGM51242_CS_PIN, FALSE)
#defineSGM51242_CLK_HIGH() gpio_bits_write(SGM51242_CLK_GPIO, SGM51242_CLK_PIN, TRUE)#defineSGM51242_CLK_LOW() gpio_bits_write(SGM51242_CLK_GPIO, SGM51242_CLK_PIN, FALSE)
#defineSGM51242_MOSI_HIGH() gpio_bits_write(SGM51242_MOSI_GPIO, SGM51242_MOSI_PIN, TRUE)#defineSGM51242_MOSI_LOW() gpio_bits_write(SGM51242_MOSI_GPIO, SGM51242_MOSI_PIN, FALSE)
#defineSGM51242_READ_MISO() gpio_input_data_bit_read(SGM51242_MISO_GPIO,SGM51242_MISO_PIN)
//ADC register address definetypedef enum {NOP_REG = 0x00,//0000 SEQUENCE_REG= 0x02,//0010 CONTROL_REG= 0x03,//0011 PIN_CONFIG_REG= 0x04,//0100 PULLDOWN_CONFIG_REG = 0x06,//0110 READBACK_MODE_REG = 0x07,//0111 POWERDOWN_AND_REFCTRL_REG = 0x0B,//1011 SOFTWARE_RESET_REG = 0x0F,//1111}sgm51242_reg_addr_e;
//control register#define SGM51242_CTRL_REG_BUFFER(x) (((x) & 0x0001) << 9)typedef enum { BUFFER_CONFIG_DISABLE = 0, //default BUFFER_CONFIG_ENABLE = 1,}sgm51242_control_reg_auxiliary_buffer_config_e;
#define SGM51242_CTRL_REG_LOCK(x) (((x) & 0x0001) << 7)typedef enum { LOCK_CONFIG_DISABLE = 0, //default LOCK_CONFIG_ENABLE = 1,}sgm51242_control_reg_lock_config_e;
#define SGM51242_CTRL_REG_RANGE(x) (((x) & 0x0001) << 5)typedef enum { INPUT_RANGE_0_VREF = 0, //default INPUT_RANGE_0_2VREF = 1,}sgm51242_control_reg_input_range_config_e;
//pin configuration register#define SGM51242_PIN_REG_INPUT_MODE 0x03 //IN0 and IN1 as ADC input
//sequence register#define SGM51242_SEQUENCE_REG_VDD_MONITOR(x) (((x) & 0x0001) << 10)typedef enum { VDD_MONITOR_DISABLE = 0, //default VDD_MONITOR_ENABLE = 1,}sgm51242_sequence_reg_vdd_monitor_e;
#define SGM51242_SEQUENCE_REG_REP(x) (((x) & 0x0001) << 9)typedef enum { REPETITION_DISABLE = 0, //default REPETITION_ENABLE = 1,}sgm51242_sequence_reg_repetition_e;
#define SGM51242_SEQUENCE_REG_TEMP(x) (((x) & 0x0001) << 8)typedef enum { TEMP_DISABLE = 0, //default TEMP_ENABLE = 1,}sgm51242_sequence_reg_temp_e;
#define SGM51242_SEQUENCE_REG_CONVERSION 0x03 //IN0 and IN1 in conversion sequence
//power-down and reference control register#define SGM51242_POWERDOWN_AND_REFCTRL_REG_PD_ALL(x) (((x) & 0x0001) << 10)typedef enum { PD_ALL_D9_BIT = 0, //default PD_ALL_POWERDOWN = 1,}sgm51242_pd_and_ref_reg_pd_all_e;
#define SGM51242_POWERDOWN_AND_REFCTRL_REG_EN_REF(x) (((x) & 0x0001) << 9)typedef enum { EN_REF_DISABLE = 0, //default EN_REF_ENABLE = 1,}sgm51242_pd_and_ref_reg_en_ref_e;
//software reset register#define SGM51242_SOFTWARE_RESET_VALUE (0x7DAC)
//readback mode register#define SGM51242_READBACK_MODE_REG_EN(x) (((x) & 0x0001) << 6)typedef enum { READBACK_DISABLE = 0, //default READBACK_ENABLE = 1,}sgm51242_readback_mode_reg_en_e;
#define SGM51242_READBACK_REG_VALUE (0x3840)
//pull-down configuration register#define SGM51242_PULLDOWN_REG_PD_CONFIG(x) (x)typedef enum { PULLDOWN_85K_DISABLE = 0x00, //default PULLDOWN_85K_ENABLE = 0xFF,}sgm51242_pulldown_reg_pd_en_e;
//ADC channel addresstypedef enum { ADC_CHANNEL_ADDR_0 = 0x00, ADC_CHANNEL_ADDR_1 = 0x01,}sgm51242_adc_chnnel_addr_e;
extern void sgm51242_delay_us(uint16_t delay_us);extern void sgm51242_init(void);extern void sgm51242_write_register(uint16_t addr, uint16_t value);extern uint16_t sgm51242_read_register(uint16_t addr);extern uint16_t sgm51242_read_adc_data(void);extern void sgm51242_software_reset(void);extern void sgm51242_spi_test(void);extern uint16_t sgm51242_rw_data(uint16_t data);extern void sgm51242_sequence_reg_config(void);
#endif /* __SGM51242_H__ */
再附上驱动代码的源文件:
#include "sgm51242.h"
//uint16_t write_data = 0;
uint16_t read_data = 0;
//uint16_t send_data = 0;
void sgm51242_delay_us(uint16_t delay_us)
{
uint16_t i;
for(i = 0; i < delay_us; i++)
{
;
}
}
uint8_t sgm51242_write(uint16_t value)
{
uint8_t i;
for(i = 0; i < 16; i++)
{
SGM51242_CLK_HIGH();
if (value & 0x8000)
{
SGM51242_MOSI_HIGH();
}
else
{
SGM51242_MOSI_LOW();
}
sgm51242_delay_us(2);
value <<= 1;
SGM51242_CLK_LOW();
sgm51242_delay_us(2);
}
//sgm51242_delay_us(2);
return 0;
}
uint16_t sgm51242_read(void)
{
uint16_t read_data = 0;
uint8_t i;
for(i = 0; i<16; i++)
{
SGM51242_CLK_LOW();
sgm51242_delay_us(2);
SGM51242_CLK_HIGH();
read_data = read_data << 1;
if(SGM51242_READ_MISO())
{
read_data |= 0x0001;
}
else
{
read_data &= ~0x0001;
}
sgm51242_delay_us(2);
}
return read_data;
}
/*sgm51242 init config*/
void sgm51242_init(void)
{
uint16_t write_data = 0;
SGM51242_CS_HIGH();
//config readback register
write_data = SGM51242_READBACK_MODE_REG_EN(READBACK_ENABLE);
sgm51242_write_register(READBACK_MODE_REG, write_data);
#if 1
//config sequence register
write_data = SGM51242_SEQUENCE_REG_VDD_MONITOR(VDD_MONITOR_DISABLE) \
| SGM51242_SEQUENCE_REG_REP(REPETITION_ENABLE) \
| SGM51242_SEQUENCE_REG_TEMP(TEMP_DISABLE) \
| SGM51242_SEQUENCE_REG_CONVERSION;
sgm51242_write_register(SEQUENCE_REG, write_data);
#endif
//config control register
write_data = SGM51242_CTRL_REG_BUFFER(BUFFER_CONFIG_DISABLE)\
| SGM51242_CTRL_REG_LOCK(LOCK_CONFIG_DISABLE)\
| SGM51242_CTRL_REG_RANGE(INPUT_RANGE_0_VREF);
sgm51242_write_register(CONTROL_REG, write_data);
//config pin configuration register
write_data = SGM51242_PIN_REG_INPUT_MODE;
sgm51242_write_register(PIN_CONFIG_REG, write_data);
//config power-down and reference control register
write_data = SGM51242_POWERDOWN_AND_REFCTRL_REG_PD_ALL(PD_ALL_D9_BIT)\
| SGM51242_POWERDOWN_AND_REFCTRL_REG_EN_REF(EN_REF_DISABLE);
sgm51242_write_register(POWERDOWN_AND_REFCTRL_REG, write_data);
//config pull-down configuration register
write_data = SGM51242_PULLDOWN_REG_PD_CONFIG(PULLDOWN_85K_DISABLE);
sgm51242_write_register(PULLDOWN_CONFIG_REG, write_data);
SGM51242_CS_HIGH();
}
/**/
/**/
uint16_t sgm51242_rw_data(uint16_t data)
{
uint16_t read_data = 0;
while(spi_i2s_flag_get(ADC_SPI_TYPE, SPI_I2S_TDBE_FLAG) == RESET);
spi_i2s_data_transmit(ADC_SPI_TYPE, data);
while(spi_i2s_flag_get(ADC_SPI_TYPE, SPI_I2S_RDBF_FLAG) == RESET);
read_data = spi_i2s_data_receive(ADC_SPI_TYPE);
return read_data;
}
void sgm51242_send_data(uint16_t write_data)
{
while(spi_i2s_flag_get(ADC_SPI_TYPE, SPI_I2S_TDBE_FLAG) == RESET);
spi_i2s_data_transmit(ADC_SPI_TYPE, write_data);
}
uint16_t sgm51242_read_data(void)
{
uint16_t read_data = 0;
while(spi_i2s_flag_get(ADC_SPI_TYPE, SPI_I2S_RDBF_FLAG) == RESET);
read_data = spi_i2s_data_receive(ADC_SPI_TYPE);
return read_data;
}
/*write data to sgm51242 register*/
void sgm51242_write_register(uint16_t addr, uint16_t value)
{
uint16_t data_in = 0x0000;
data_in = addr;
data_in = (data_in << 11) | (value & 0x07FF);
SGM51242_CS_LOW();
sgm51242_rw_data(data_in);
//sgm51242_write(data_in);
SGM51242_CS_HIGH();
}
/*read data from sgm51242 register*/
uint16_t sgm51242_read_register(uint16_t addr)
{
uint16_t data_in = 0x0000;
uint16_t data_out = 0x0000;
data_in = addr;
data_in = (data_in << 2) | SGM51242_READBACK_REG_VALUE; //first, write data to readback register
SGM51242_CS_LOW();
sgm51242_rw_data(data_in);
SGM51242_CS_HIGH();
sgm51242_delay_us(1);
SGM51242_CS_LOW();
data_in = 0x0000;
data_out = sgm51242_rw_data(data_in); //second, read register data from config addr
SGM51242_CS_HIGH();
return data_out;
}
/*read adc conversion data from adc data register*/
uint16_t sgm51242_read_adc_data(void)
{
uint16_t data_out = 0x0000;
SGM51242_CS_LOW();
sgm51242_delay_us(60);
data_out = sgm51242_rw_data(0x0000);
//data_out = sgm51242_read();
SGM51242_CS_HIGH();
sgm51242_delay_us(6);
return data_out;
}
/*config sequence register*/
void sgm51242_sequence_reg_config(void)
{
uint16_t write_data = 0;
//config sequence register
write_data = SGM51242_SEQUENCE_REG_VDD_MONITOR(VDD_MONITOR_DISABLE) \
| SGM51242_SEQUENCE_REG_REP(REPETITION_ENABLE) \
| SGM51242_SEQUENCE_REG_TEMP(TEMP_DISABLE) \
| SGM51242_SEQUENCE_REG_CONVERSION;
sgm51242_write_register(SEQUENCE_REG, write_data);
}
/*reset sgm51242*/
void sgm51242_software_reset(void)
{
sgm51242_write_register(SOFTWARE_RESET_REG, SGM51242_SOFTWARE_RESET_VALUE);
sgm51242_delay_us(1000); //need delay?
}
/*sgm51242 spi test*/
void sgm51242_spi_test(void)
{
//uint16_t vdd_flag = 0;
//read sequence register
//read_data = sgm51242_read_register(SEQUENCE_REG);
//read_data = sgm51242_read_adc_data();
//if((read_data>>12)==1)
//{
// vdd_flag = 1;
//}
}
以上向大家展示了一款ADC芯片的驱动代码设计,虽然有些函数由于宏函数和宏定义比较多而看上去比较繁琐复杂,但是其可维护性和可读性却大大提升,希望对大家有一些帮助;你有更好的idea也欢迎来贴分享!毕竟山外有山,人外有人嘛。
就不会把代码放到代码框里发吗
页:
[1]