#申请原创# #技术资源#
大家直接看标题可能有点疑惑,所以我这里先解释一下,所谓的“多板多芯片且引脚复用”其实是这个意思: 就是一个产品有多个PCB板,每个板子上都有两个及以上的同样的芯片;且由于MCU引脚资源有限的问题会共用GPIO引脚以实现分时复用。 以我以前接触过的产品为例,上面有两块PCB板,一块带MCU芯片的CPU板,上面有两颗IS3980S芯片;一块带输入检测的IO板,上面也有两颗IS3980S芯片,且两块PCB板通过连接线束连接,主要是将IO板上的IS3980S芯片检测到的输入数据通过总线回传到MCU。 另外,由于MCU引脚资源有限,PCB板上的两颗IS3980S芯片的SCLK、MISO和MOSI三根信号线是共用一组GPIO引脚的,各自通过NSS片选信号进行数据读取的切换,其实就是类似于SPI的一主多从拓扑;同样的,IO板上的两颗IS3980S芯片的SCLK、MISO和MOSI三根信号线是共用另外一组GPIO引脚的,各自通过NSS片选信号进行数据读取的切换。 其实说了半天,其通过下面的框图基本上就可以知道是什么硬件拓扑了,更一目了然: 这里的IS3980S其实是一款支持8通道隔离式数字输入检测的接收器芯片,走的是四线串行总线接口,即MCU端可以用硬件SPI或者模拟SPI来实现数据读取。另外,IS3980S其实也支持菊花链连接,但是我们考虑到应用场景的抗干扰性能和数据稳定性,我们没有采用这种方式,而是采用了通过NSS片选信号进行分时复用读取数据的方式: 那对于类似我们这样的硬件设计,软件的驱动代码应该怎么实现比较好呢?首先的原则当然是驱动代码的各个函数接口尽量保证只有一个。鉴于此,我是按照下面这种方式实现的: 在原始的驱动代码的各个函数接口的形参里面加入所谓索引index的概念,比如既然有两块PCB,那就加个PCB索引pcb_index来识别是CPU板还是IO板;既然有两个芯片来复用同一组IO引脚,其实本质上是两个NSS片选信号,那就加个NSS索引nss_index来识别是哪个芯片处于激活active状态,哪个芯片处于非工作状态。
然后可以定义几个宏,比如各个板子的芯片的最大个数是2,然后需要区分是CPU板还是IO板的芯片,这个是对应pcb_index的,;识别PCB板类型后还要进一步区分是哪个芯片,这个是对应nss_index的,得到相关的宏定义如下: - //pcb_index
- #define IS3980S_MAX (2)
- #define CPU_IS3980S (0)
- #define KEY_IS3980S (1)
- //nss_index
- #define IS3980S_NSS_MAX 2
- #define CPU_IS3980S_NSS1 0
- #define CPU_IS3980S_NSS2 1
- #define KEY_IS3980S_NSS1 0
- #define KEY_IS3980S_NSS2 1
然后对于SCLK、MOSI、MISO和NSS信号绑定MCU的GPIO引脚,毫无疑问是通过宏定义来完成,并以PCB板名称来作为前缀以识别,比如对于NSS引脚,可以参考如下定义: - #define CPU_IS3980S_NSS1_GPIO GPIOB
- #define CPU_IS3980S_NSS2_GPIO GPIOB
- #define CPU_IS3980S_NSS1_PIN GPIO_PINS_6
- #define CPU_IS3980S_NSS2_PIN GPIO_PINS_1
- #define KEY_IS3980S_NSS1_GPIO GPIOA
- #define KEY_IS3980S_NSS2_GPIO GPIOA
- #define KEY_IS3980S_NSS1_PIN GPIO_PINS_9
- #define KEY_IS3980S_NSS2_PIN GPIO_PINS_10
这里有个建议,即使一组串行信号连接在同一个GPIO组,定义的时候也要单独分开,以增强代码扩展性和维护性。
接着就可以通过宏定义的方式并结合GPIO引脚及pcb_index和nss_index参数来实现引脚分时切换的代码,比如对于NSS、SCLK(MOSI类似)和MISO,可以实现如下: - #define IS3980S_NSS_HIGH(pcb_index, nss_index) \
- do{ \
- switch(pcb_index) \
- { \
- case CPU_IS3980S: \
- { \
- switch(nss_index) \
- { \
- case CPU_IS3980S_NSS1: \
- gpio_bits_write(CPU_IS3980S_NSS1_GPIO, CPU_IS3980S_NSS1_PIN, TRUE); \
- break; \
- case CPU_IS3980S_NSS2: \
- gpio_bits_write(CPU_IS3980S_NSS2_GPIO, CPU_IS3980S_NSS2_PIN, TRUE); \
- break; \
- default: \
- break; \
- }\
- }\
- break; \
- case KEY_IS3980S: \
- { \
- switch(nss_index) \
- { \
- case KEY_IS3980S_NSS1: \
- gpio_bits_write(KEY_IS3980S_NSS1_GPIO, KEY_IS3980S_NSS1_PIN, TRUE); \
- break; \
- case KEY_IS3980S_NSS2: \
- gpio_bits_write(KEY_IS3980S_NSS2_GPIO, KEY_IS3980S_NSS2_PIN, TRUE); \
- break; \
- default: \
- break; \
- }\
- }\
- break; \
- default: \
- break; \
- }\
- }while(0);
- #define IS3980S_SCK_HIGH(pcb_index) \
- do{ \
- switch(pcb_index) \
- { \
- case CPU_IS3980S: \
- gpio_bits_write(CPU_IS3980S_SCK_GPIO, CPU_IS3980S_SCK_PIN, TRUE); \
- break; \
- case KEY_IS3980S: \
- gpio_bits_write(KEY_IS3980S_SCK_GPIO, KEY_IS3980S_SCK_PIN, TRUE); \
- break; \
- default: \
- break; \
- }\
- }while(0);
- #define IS3980S_READ_MISO_CPU() gpio_input_data_bit_read(CPU_IS3980S_MISO_GPIO, CPU_IS3980S_MISO_PIN)
- #define IS3980S_READ_MISO_KEY() gpio_input_data_bit_read(KEY_IS3980S_MISO_GPIO, KEY_IS3980S_MISO_PIN)
然后对于这种上电时候需要通过MCU对其进行初始化配置的芯片,这种实现方法以芯片最大个数为for循环的条件即可调用一次初始化接口就能完成芯片初始化,如下所示: - void is3980s_all_init(void)
- {
- uint8_t i = 0;
- uint8_t j = 0;
- for(i=0; i<IS3980S_MAX; i++)
- {
- for(j=0; j<IS3980S_NSS_MAX; j++)
- {
- is3980s_init(i, j);
- }
- }
- }
下面就与大家展示一下这个IS3980S芯片的多板多芯片且引脚复用的驱动代码:
头文件如下所示: - #ifndef __IS3980S_H__
- #define __IS3980S_H__
- /*SPI data frame length (byte)*/
- #define IS3980S_SPI_DATA_LEN 3
- /*hardware interface*/
- #define IS3980S_MAX (2)
- #define CPU_IS3980S (0)
- #define KEY_IS3980S (1)
- #define IS3980S_NSS_MAX 2
- #define CPU_IS3980S_NSS1 0
- #define CPU_IS3980S_NSS2 1
- #define KEY_IS3980S_NSS1 0
- #define KEY_IS3980S_NSS2 1
- #define CPU_IS3980S_GPIO GPIOB
- #define CPU_IS3980S_SCK_GPIO GPIOB
- #define CPU_IS3980S_MOSI_GPIO GPIOB
- #define CPU_IS3980S_MISO_GPIO GPIOB
- #define CPU_IS3980S_NSS1_GPIO GPIOB
- #define CPU_IS3980S_NSS2_GPIO GPIOB
- #define CPU_IS3980S_SCK_PIN GPIO_PINS_7
- #define CPU_IS3980S_MOSI_PIN GPIO_PINS_9
- #define CPU_IS3980S_MISO_PIN GPIO_PINS_8
- #define CPU_IS3980S_NSS1_PIN GPIO_PINS_6
- #define CPU_IS3980S_NSS2_PIN GPIO_PINS_1
- #define KEY_IS3980S_GPIO GPIOB
- #define KEY_IS3980S_SCK_GPIO GPIOB
- #define KEY_IS3980S_MOSI_GPIO GPIOB
- #define KEY_IS3980S_MISO_GPIO GPIOB
- #define KEY_IS3980S_NSS1_GPIO GPIOA
- #define KEY_IS3980S_NSS2_GPIO GPIOA
- #define KEY_IS3980S_SCK_PIN GPIO_PINS_3
- #define KEY_IS3980S_MOSI_PIN GPIO_PINS_5
- #define KEY_IS3980S_MISO_PIN GPIO_PINS_4
- #define KEY_IS3980S_NSS1_PIN GPIO_PINS_9
- #define KEY_IS3980S_NSS2_PIN GPIO_PINS_10
- #define IS3980S_NSS_HIGH(pcb_index, nss_index) \
- do{ \
- switch(pcb_index) \
- { \
- case CPU_IS3980S: \
- { \
- switch(nss_index) \
- { \
- case CPU_IS3980S_NSS1: \
- gpio_bits_write(CPU_IS3980S_NSS1_GPIO, CPU_IS3980S_NSS1_PIN, TRUE); \
- break; \
- case CPU_IS3980S_NSS2: \
- gpio_bits_write(CPU_IS3980S_NSS2_GPIO, CPU_IS3980S_NSS2_PIN, TRUE); \
- break; \
- default: \
- break; \
- }\
- }\
- break; \
- case KEY_IS3980S: \
- { \
- switch(nss_index) \
- { \
- case KEY_IS3980S_NSS1: \
- gpio_bits_write(KEY_IS3980S_NSS1_GPIO, KEY_IS3980S_NSS1_PIN, TRUE); \
- break; \
- case KEY_IS3980S_NSS2: \
- gpio_bits_write(KEY_IS3980S_NSS2_GPIO, KEY_IS3980S_NSS2_PIN, TRUE); \
- break; \
- default: \
- break; \
- }\
- }\
- break; \
- default: \
- break; \
- }\
- }while(0);
- #define IS3980S_NSS_LOW(pcb_index, nss_index) \
- do{ \
- switch(pcb_index) \
- { \
- case CPU_IS3980S: \
- { \
- switch(nss_index) \
- { \
- case CPU_IS3980S_NSS1: \
- gpio_bits_write(CPU_IS3980S_NSS1_GPIO, CPU_IS3980S_NSS1_PIN, FALSE); \
- break; \
- case CPU_IS3980S_NSS2: \
- gpio_bits_write(CPU_IS3980S_NSS2_GPIO, CPU_IS3980S_NSS2_PIN, FALSE); \
- break; \
- default: \
- break; \
- }\
- }\
- break; \
- case KEY_IS3980S: \
- { \
- switch(nss_index) \
- { \
- case KEY_IS3980S_NSS1: \
- gpio_bits_write(KEY_IS3980S_NSS1_GPIO, KEY_IS3980S_NSS1_PIN, FALSE); \
- break; \
- case KEY_IS3980S_NSS2: \
- gpio_bits_write(KEY_IS3980S_NSS2_GPIO, KEY_IS3980S_NSS2_PIN, FALSE); \
- break; \
- default: \
- break; \
- }\
- }\
- break; \
- default: \
- break; \
- }\
- }while(0);
- #define IS3980S_SCK_HIGH(pcb_index) \
- do{ \
- switch(pcb_index) \
- { \
- case CPU_IS3980S: \
- gpio_bits_write(CPU_IS3980S_SCK_GPIO, CPU_IS3980S_SCK_PIN, TRUE); \
- break; \
- case KEY_IS3980S: \
- gpio_bits_write(KEY_IS3980S_SCK_GPIO, KEY_IS3980S_SCK_PIN, TRUE); \
- break; \
- default: \
- break; \
- }\
- }while(0);
- #define IS3980S_SCK_LOW(pcb_index) \
- do{ \
- switch(pcb_index) \
- { \
- case CPU_IS3980S: \
- gpio_bits_write(CPU_IS3980S_SCK_GPIO, CPU_IS3980S_SCK_PIN, FALSE); \
- break; \
- case KEY_IS3980S: \
- gpio_bits_write(KEY_IS3980S_SCK_GPIO, KEY_IS3980S_SCK_PIN, FALSE); \
- break; \
- default: \
- break; \
- }\
- }while(0);
- #define IS3980S_MOSI_HIGH(pcb_index) \
- do{ \
- switch(pcb_index) \
- { \
- case CPU_IS3980S: \
- gpio_bits_write(CPU_IS3980S_MOSI_GPIO, CPU_IS3980S_MOSI_PIN, TRUE); \
- break; \
- case KEY_IS3980S: \
- gpio_bits_write(KEY_IS3980S_MOSI_GPIO, KEY_IS3980S_MOSI_PIN, TRUE); \
- break; \
- default: \
- break; \
- }\
- }while(0);
- #define IS3980S_MOSI_LOW(pcb_index) \
- do{ \
- switch(pcb_index) \
- { \
- case CPU_IS3980S: \
- gpio_bits_write(CPU_IS3980S_MOSI_GPIO, CPU_IS3980S_MOSI_PIN, FALSE); \
- break; \
- case KEY_IS3980S: \
- gpio_bits_write(KEY_IS3980S_MOSI_GPIO, KEY_IS3980S_MOSI_PIN, FALSE); \
- break; \
- default: \
- break; \
- }\
- }while(0);
- #define IS3980S_READ_MISO_CPU() gpio_input_data_bit_read(CPU_IS3980S_MISO_GPIO, CPU_IS3980S_MISO_PIN)
- #define IS3980S_READ_MISO_KEY() gpio_input_data_bit_read(KEY_IS3980S_MISO_GPIO, KEY_IS3980S_MISO_PIN)
- //delay time
- #define IS3980S_DELAY_TIME 25
- #define IS3980S_SYNC_TIME 10
- /*SPI data*/
- typedef struct
- {
- u8 ctrl_byte; //control byte
- u8 addr_byte; //address byte
- u8 data_byte; //data byte
- }is3980s_spi_data_t;
- extern is3980s_spi_data_t is3980s_data;
- /*chip register address*/
- typedef enum {
- IS3980S_CHAN_STATUS_REG = 0x00, //status register,8bit,only read,show input status of 8 channels
- IS3980S_BDNC_MODE0_REG = 0x01, //filter mode set register, A1~A4 channels config
- IS3980S_BDNC_MODE1_REG = 0x02, //A5~A8 channels config
- IS3980S_BDNC_DLY0_REG = 0x03, //filter time set register, A1~A4 channels config
- IS3980S_BDNC_DLY1_REG = 0x04, //A5~A8 channels config
- }is3980s_reg_addr_e;
- /*read and write cmd config*/
- typedef enum {
- IS3980S_RW_WRITE = 0,
- IS3980S_RW_READ = 1,
- }is3980s_rw_command_e;
- /*define device id to write low 4 bits of control byte, CID[3:0]*/
- typedef enum {
- IS3980S_CID_0 = 0, //connect spi master when config which CID
- IS3980S_CID_1,
- IS3980S_CID_2,
- IS3980S_CID_3,
- IS3980S_CID_4,
- }is3980s_cid_e;
- /*define boradcast cmd to write bit7 of control byte*/
- typedef enum {
- IS3980S_BRCT_DISABLE = 0, //only operate CID device of addressing
- IS3980S_BRCT_ENABLE = 1, //operate all CID devices of daisy chain
- }is3980s_op_brct_e;
- /*define common rw data of control byte*/
- typedef enum {
- CTRL_DATA_BRCT_W = 0x80, //broadcast+write: 1000 0000
- CTRL_DATA_W_CID_0 = 0x00, //unicast+write CID_0: 0000 0000
- CTRL_DATA_W_CID_1 = 0x08, //unicast+write CID_1: 0000 1000
- CTRL_DATA_R_CID_0 = 0x40, //unicast+read CID_0: 0100 0000
- CTRL_DATA_R_CID_1 = 0x48, //unicast+read CID_1: 0100 1000
- CTRL_DATA_R_CID_2 = 0x44, //unicast+read CID_2: 0100 0100
- CTRL_DATA_R_CID_3 = 0x4C, //unicast+read CID_3: 0100 1100
- CTRL_DATA_R_CID_4 = 0x42, //unicast+read CID_0: 0100 0010
- }is3980s_op_ctrl_data_e;
- extern void is3980s_all_init(void);
- extern void is3980s_init(uint8_t pcb_index, uint8_t nss_index);
- extern void is3980s_write(uint8_t pcb_index, uint8_t nss_index, uint8_t *write_buff, uint8_t len);
- extern void is3980s_read(uint8_t pcb_index, uint8_t nss_index, uint8_t *read_buff, uint8_t len);
- extern void is3980s_write_byte(uint8_t pcb_index, uint8_t nss_index, uint8_t write_byte);
- extern uint8_t is3980s_read_byte(uint8_t pcb_index, uint8_t nss_index);
- extern void is3980s_sync(uint8_t pcb_index, uint8_t nss_index);
- extern void is3980s_set_filter(uint8_t pcb_index, uint8_t nss_index, uint8_t filter_mode, uint8_t filter_time);
- #endif /* __IS3980S_H__ */
源文件如下所示: - #include "is3980s.h"
- is3980s_spi_data_t is3980s_data;
- uint8_t test_data[2];
- /* init all IS3980S CHIP */
- void is3980s_all_init(void)
- {
- uint8_t i = 0;
- uint8_t j = 0;
- for(i=0; i<IS3980S_MAX; i++)
- {
- for(j=0; j<IS3980S_NSS_MAX; j++)
- {
- is3980s_init(i, j);
- }
- }
- }
- /* config IS3980S */
- void is3980s_init(uint8_t pcb_index, uint8_t nss_index)
- {
- uint8_t spi_frame[IS3980S_SPI_DATA_LEN]; //control+address+data
- /*pin config*/
- IS3980S_NSS_HIGH(pcb_index, nss_index);
- IS3980S_SCK_HIGH(pcb_index);
- IS3980S_MOSI_LOW(pcb_index);
- /*config when power on to make sure chip can work stable*/
- //write data 0x55 to address 0x0A
- spi_frame[0] = CTRL_DATA_BRCT_W;
- spi_frame[1] = 0x0A;
- spi_frame[2] = 0x55;
- is3980s_write(pcb_index, nss_index, spi_frame, IS3980S_SPI_DATA_LEN);
- //write data 0x44 to address 0x09
- spi_frame[1] = 0x09;
- spi_frame[2] = 0x44;
- is3980s_write(pcb_index, nss_index, spi_frame, IS3980S_SPI_DATA_LEN);
- //write data 0x00 to address 0x0A
- spi_frame[1] = 0x0A;
- spi_frame[2] = 0x00;
- is3980s_write(pcb_index, nss_index, spi_frame, IS3980S_SPI_DATA_LEN);
- }
- /*inaccuracy delay*/
- static void is3980s_delay(uint32_t count)
- {
- uint32_t i;
-
- for(i = 0; i < count; i++)
- {
- __asm("nop");
- }
- }
- /*get miso pin data*/
- static uint8_t is3980s_get_miso(uint8_t pcb_index)
- {
- uint8_t value = 0;
-
- if(CPU_IS3980S == pcb_index)
- {
- value = IS3980S_READ_MISO_CPU();
- }
- else if(KEY_IS3980S == pcb_index)
- {
- value = IS3980S_READ_MISO_KEY();
- }
- return value;
- }
- /*write datas*/
- void is3980s_write(uint8_t pcb_index, uint8_t nss_index, uint8_t *write_buff, uint8_t len)
- {
- uint8_t i;
-
- for(i=0; i < len; i++)
- {
- is3980s_write_byte(pcb_index, nss_index, write_buff[i]);
- }
- }
- /*read datas*/
- void is3980s_read(uint8_t pcb_index, uint8_t nss_index, uint8_t *read_buff, uint8_t len)
- {
- uint8_t i;
-
- for(i=0; i < len; i++)
- {
- read_buff[i] = is3980s_read_byte(pcb_index, nss_index);
- }
- }
- /*write byte data*/
- void is3980s_write_byte(uint8_t pcb_index, uint8_t nss_index, uint8_t write_byte)
- {
- uint8_t i;
-
- IS3980S_NSS_LOW(pcb_index, nss_index);
- is3980s_delay(IS3980S_DELAY_TIME);
- for(i = 0; i<8; i++)
- {
- IS3980S_SCK_LOW(pcb_index);
- if(write_byte & 0x80)
- {
- IS3980S_MOSI_HIGH(pcb_index);
- }
- else
- {
- IS3980S_MOSI_LOW(pcb_index);
- }
- write_byte <<= 1;
- is3980s_delay(IS3980S_DELAY_TIME);
- IS3980S_SCK_HIGH(pcb_index);
- is3980s_delay(IS3980S_DELAY_TIME);
- }
- is3980s_delay(IS3980S_DELAY_TIME);
- IS3980S_NSS_HIGH(pcb_index, nss_index);
- is3980s_delay(IS3980S_DELAY_TIME);
- }
- /*read byte data*/
- uint8_t is3980s_read_byte(uint8_t pcb_index, uint8_t nss_index)
- {
- uint8_t read_byte = 0;
- uint8_t i;
- IS3980S_NSS_LOW(pcb_index, nss_index);
- is3980s_delay(3);
- for(i = 0; i<8; i++)
- {
- IS3980S_SCK_LOW(pcb_index);
- is3980s_delay(IS3980S_DELAY_TIME);
- IS3980S_SCK_HIGH(pcb_index);
- read_byte = read_byte << 1;
- //is3980s_delay(5);
- if(is3980s_get_miso(pcb_index))
- {
- read_byte |= 0x01;
- }
- else
- {
- read_byte &= ~0x01;
- }
- //IS3980S_SCK_HIGH(pcb_index);
- is3980s_delay(IS3980S_DELAY_TIME);
- }
- is3980s_delay(IS3980S_DELAY_TIME);
- IS3980S_NSS_HIGH(pcb_index, nss_index);
- is3980s_delay(3);
- return read_byte;
- }
- /*send sync signal*/
- void is3980s_sync(uint8_t pcb_index, uint8_t nss_index)
- {
- IS3980S_NSS_HIGH(pcb_index, nss_index);
- IS3980S_SCK_LOW(pcb_index);
- is3980s_delay(IS3980S_SYNC_TIME);
- IS3980S_SCK_HIGH(pcb_index);
- is3980s_delay(IS3980S_SYNC_TIME);
- IS3980S_SCK_HIGH(pcb_index);
- is3980s_delay(IS3980S_SYNC_TIME);
- }
- /*set filter time*/
- void is3980s_set_filter(uint8_t pcb_index, uint8_t nss_index, uint8_t filter_mode, uint8_t filter_time)
- {
- uint8_t spi_frame[IS3980S_SPI_DATA_LEN];
- is3980s_sync(pcb_index, nss_index);
- /*config filter mode for A1~A4 channel*/
- spi_frame[0] = CTRL_DATA_BRCT_W;
- spi_frame[1] = IS3980S_BDNC_MODE0_REG;
- spi_frame[2] = filter_mode;
- is3980s_write(pcb_index, nss_index, spi_frame, IS3980S_SPI_DATA_LEN);
- /*config filter mode for A5~A8 channel*/
- spi_frame[1] = IS3980S_BDNC_MODE1_REG;
- spi_frame[2] = filter_mode;
- is3980s_write(pcb_index, nss_index, spi_frame, IS3980S_SPI_DATA_LEN);
- /*config filter time for A5~A8 channel*/
- spi_frame[1] = IS3980S_BDNC_DLY0_REG;
- spi_frame[2] = filter_time;
- is3980s_write(pcb_index, nss_index, spi_frame, IS3980S_SPI_DATA_LEN);
- /*config filter time for A5~A8 channel*/
- spi_frame[1] = IS3980S_BDNC_DLY1_REG;
- spi_frame[2] = filter_time;
- is3980s_write(pcb_index, nss_index, spi_frame, IS3980S_SPI_DATA_LEN);
- //readback test
- // is3980s_write_byte(pcb_index, nss_index, CTRL_DATA_R_CID_0);
- // is3980s_write_byte(pcb_index, nss_index, IS3980S_BDNC_DLY0_REG);
- // test_data[0] = is3980s_read_byte();
- // is3980s_write_byte(pcb_index, nss_index, CTRL_DATA_R_CID_1);
- // is3980s_write_byte(pcb_index, nss_index, IS3980S_BDNC_DLY1_REG);
- // test_data[1] = is3980s_read_byte(pcb_index, nss_index);
- }
显而易见,基本上每个函数接口都带有两个形参: uint8_t pcb_index
uint8_t nss_index 最原始的驱动代码其实是下面这个造型: 当我们在实际应用的时候,首先就要分时复用,通过NSS信号来激活其中一个芯片,类似下面的代码,拉高NSS信号即deactive芯片: - static void cpu_spi_active_config(uint8_t chip_index)
- {
- switch(chip_index)
- {
- case CPU_SPI_IS3980S_ENCODER:
- {
- IS3980S_NSS_HIGH(CPU_IS3980S, CPU_IS3980S_NSS2);
- break;
- }
- case CPU_SPI_IS3980S_DI:
- {
- IS3980S_NSS_HIGH(CPU_IS3980S, CPU_IS3980S_NSS1);
- break;
- }
- default:
- {
- IS3980S_NSS_HIGH(CPU_IS3980S, CPU_IS3980S_NSS1);
- IS3980S_NSS_HIGH(CPU_IS3980S, CPU_IS3980S_NSS2);
- break;
- }
- }
- }
- static void key_spi_active_config(uint8_t chip_index)
- {
- switch(chip_index)
- {
- case KEY_SPI_IS3980S_CN631:
- {
- IS3980S_NSS_HIGH(KEY_IS3980S, KEY_IS3980S_NSS2);
- break;
- }
- case KEY_SPI_IS3980S_CN748:
- {
- IS3980S_NSS_HIGH(KEY_IS3980S, KEY_IS3980S_NSS1);
- break;
- }
- default:
- {
- IS3980S_NSS_HIGH(KEY_IS3980S, KEY_IS3980S_NSS1);
- IS3980S_NSS_HIGH(KEY_IS3980S, KEY_IS3980S_NSS2);
- break;
- }
- }
- }
然后在对应位置使用下面的接口即可进行数据读取: - di_data0 = di_thread(CPU_IS3980S, CPU_IS3980S_NSS1);
- di_data1 = di_thread(CPU_IS3980S, CPU_IS3980S_NSS2);
- di_data2 = di_thread(KEY_IS3980S, KEY_IS3980S_NSS1);
- di_data3 = di_thread(KEY_IS3980S, KEY_IS3980S_NSS2);
其中di_thread这个线程函数里面就是读写输入数据的代码,其形参也是uint8_t pcb_index和uint8_t nss_index: - uint8_t di_thread(uint8_t pcb_index, uint8_t nss_index)
- {
- uint8_t di_write_data = 0;
- uint8_t di_read_data = 0;
- //sync
- is3980s_sync(pcb_index, nss_index);
- di_write_data = di_set_cid_data(0);
- is3980s_write(pcb_index, nss_index, &di_write_data, 1);
- di_write_data = IS3980S_CHAN_STATUS_REG;
- is3980s_write(pcb_index, nss_index, &di_write_data, 1);
- is3980s_read(pcb_index, nss_index, &di_read_data, 1);
- return di_read_data;
- }
对于更多类似的硬件设计,通过这种方法实现的驱动代码里面的各个函数接口,基本上每个都会携带pcb_index和nss_index参数,然后函数里面的代码都会涉及,看着是有点复杂,但是扩展性和维护性相对来说还是不错的。当然,你还可以视具体情况增加更多的index来识别。
话说回来,这种设计肯定不是最好最优的,毕竟仁者见仁,智者见智,比如也可以通过定义结构体+表驱动法来实现;这里咱就权当是抛砖引玉,有更好的想法和设计的大神请不吝赐教~~
|