本帖最后由 dffzh 于 2025-5-26 08:57 编辑
#申请原创#
@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
- #define SGM51242_CS_HIGH() gpio_bits_write(SGM51242_CS_GPIO, SGM51242_CS_PIN, TRUE)
- #define SGM51242_CS_LOW() gpio_bits_write(SGM51242_CS_GPIO, SGM51242_CS_PIN, FALSE)
- #define SGM51242_CLK_HIGH() gpio_bits_write(SGM51242_CLK_GPIO, SGM51242_CLK_PIN, TRUE)
- #define SGM51242_CLK_LOW() gpio_bits_write(SGM51242_CLK_GPIO, SGM51242_CLK_PIN, FALSE)
- #define SGM51242_MOSI_HIGH() gpio_bits_write(SGM51242_MOSI_GPIO, SGM51242_MOSI_PIN, TRUE)
- #define SGM51242_MOSI_LOW() gpio_bits_write(SGM51242_MOSI_GPIO, SGM51242_MOSI_PIN, FALSE)
- #define SGM51242_READ_MISO() gpio_input_data_bit_read(SGM51242_MISO_GPIO,SGM51242_MISO_PIN)
- //ADC register address define
- typedef 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 address
- typedef 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也欢迎来贴分享!毕竟山外有山,人外有人嘛。
|