#申请原创#
@21小跑堂
SGM42406由8个相同的低侧驱动器组成,具备串行保护功能;并且集成了用于感性负载消磁的二极管,且可驱动不同类型的负载,例如有刷电机、继电器、发光二极管、单极步进电机等。 我们使用的是16引脚的SGM42406B,使用4线串行接口进行通信,如下图所示:
接下来我就先分享一下自己解读SGM42406芯片手册的获取到的一些主要信息,然后展示一下基于C语言的芯片驱动代码。 SGM42406属于低侧驱动芯片,所谓的低侧驱动,即指驱动芯片被放置在负载和地(GND)之间,而负载的另一端直接连接到电源正极,并通过控制芯片对地的通断,来控制负载的电源回路,该芯片的功能框图如下所示:
主要的引脚及功能描述和标注如下图所示:
对于芯片的使能引脚ENABLE这里需要注意一点: 对应SGM42406A型号,控制ENABLE为高电平,即为使能芯片工作; 对应SGM42406B型号,控制nENABLE为低电平,即为使能芯片工作。 SGM42406与MCU之间通过4线串行通信,通信时序可以参考SPI总线实现,可以用硬件SPI,也可以用软件SPI实现功能,即LATCH引脚对应CS信号,CLK对应CLOCK信号,DIN对应MOSI信号,DOUT对应MISO信号,通信时序如下图所示:
通过MCU将数据写入单个芯片的数据寄存器的时序如下图所示:
当然,很重要的一个信息就是芯片支持菊花链(Daisy-Chain)操作,其实菊花链连接在很多芯片上都有,不仅方便数据拓展,同时也节约MCU引脚资源。下面是该芯片的菊花链应用:
即级联的各个芯片共用LATCH,CLK,前一级芯片的DOUT引脚连接到下一级芯片的DIN引脚。 另外,芯片支持故障检测及状态输出,即当芯片出现过温、过流和短路现象时,会通过FAULT引脚输出低电平信号,MCU可以检测FAULT引脚的数据。然后如果想知道具体是哪个OUT输出造成的过流或者短路,可以通过回读故障寄存器的值来识别。 该芯片的主要寄存器主要包括三个,即: 数据寄存器:Data Register 芯片根据数据寄存器控制输出的开和关:
故障寄存器:Fault Register 用于记录芯片的过流和过载故障信息:
控制寄存器:Control Register 芯片通过设置控制寄存器来配置通电时间和输出PWM占空比,驱动电机时会用到:
然后我再分享一下SGM42406的基于C语言的驱动代码,主要包括两个文件,一个是SGM42406.c源文件,一个是SGM42406.h头文件,其中延时时间这块需要根据不同MCU平台及硬件参数自行调整,确保时序波形不失真的情况下可以满足速度要求。 其中头文件的主要代码如下所示,主要包括硬件GPIO配置(不同MCU可以自行修改),回调函数定义及对外函数接口声明等,另外可以通过使能和不使能SGM42406_B宏来配置为SGM42406A还是SGM42406B的驱动代码: - #ifndef __SGM42406_H__
- #define __SGM42406_H__
- #include "at32f403a_407.h"
- #include <string.h>
- #define SGM42406_EN_GPIO GPIOB
- #define SGM42406_CLK_GPIO GPIOB
- #define SGM42406_LATCH_GPIO GPIOA
- #define SGM42406_DIN_GPIO GPIOB
- #define SGM42406_FAULT_GPIO GPIOA
- #define SGM42406_DOUT_GPIO GPIOB
- #define SGM42406_EN_PIN GPIO_PINS_2
- #define SGM42406_CLK_PIN GPIO_PINS_7
- #define SGM42406_LATCH_GPIN GPIO_PINS_4 // NSS pin
- #define SGM42406_DIN_PIN GPIO_PINS_9
- #define SGM42406_FAULT_PIN GPIO_PINS_8
- #define SGM42406_DOUT_PIN GPIO_PINS_8
- #define SGM42406_CLK_HIGH() gpio_bits_write(SGM42406_CLK_GPIO, SGM42406_CLK_PIN, TRUE)
- #define SGM42406_CLK_LOW() gpio_bits_write(SGM42406_CLK_GPIO, SGM42406_CLK_PIN, FALSE)
- #define SGM42406_LATCH_HIGH() gpio_bits_write(SGM42406_LATCH_GPIO, SGM42406_LATCH_GPIN, TRUE)
- #define SGM42406_LATCH_LOW() gpio_bits_write(SGM42406_LATCH_GPIO, SGM42406_LATCH_GPIN, FALSE)
- #define SGM42406_EN_HIGH() gpio_bits_write(SGM42406_EN_GPIO, SGM42406_EN_PIN, TRUE)
- #define SGM42406_EN_LOW() gpio_bits_write(SGM42406_EN_GPIO, SGM42406_EN_PIN, FALSE)
- #define SGM42406_DIN_HIGH() gpio_bits_write(SGM42406_DIN_GPIO, SGM42406_DIN_PIN, TRUE)
- #define SGM42406_DIN_LOW() gpio_bits_write(SGM42406_DIN_GPIO, SGM42406_DIN_PIN, FALSE)
- #define SGM42406_READ_DOUT() gpio_input_data_bit_read(SGM42406_DOUT_GPIO,SGM42406_DOUT_PIN)
- #define SGM42406_READ_FAULT() gpio_input_data_bit_read(SGM42406_FAULT_GPIO,SGM42406_FAULT_PIN)
- #define SGM42406_DELAY_TIME 0 //4
- #define SGM42406_B
- typedef enum {
- SGM42406_L = 0,
- SGM42406_H,
- }sgm42406_pin_sta_e;
- typedef enum {
- SGM42406_READ_CONTORL_REG = 0,
- SGM42406_READ_DATA_REG,
- }sgm42406_read_reg_e;
- typedef struct {
- void (* set_LATCH_pin_sta)(u8 status);
- void (* set_CLK_pin_sta)(u8 status);
- void (* set_DIN_pin_sta)(u8 status);
- #ifdef SGM42406_A
- void (* set_ENABLE_pin_sta)(u8 status);
- #elif defined(SGM42406_B)
- void (* set_NENABLE_pin_sta)(u8 status);
- #endif
- u8 (* get_DOUT_pin_sta) (void);
- u8 (* get_NFAULT_pin_sta) (void);
- void (* sgm42406_delay_us) (u32 us);
- }sgm42406_driver, *sgm42406_driver_t;
- void sgm42406_init(void);
- void sgm42406_command_clk(u8 clk_times);
- s8 sgm42406_write_data(u8 *write_buff, u32 len);
- void sgm42406_read_fault_reg(u16 *read_buff, u8 chip_sum);
- void sgm42406_write_control_reg(u8 *write_buff, u32 len);
- void sgm42406_read_control_or_data_reg(sgm42406_read_reg_e reg, u8 *read_buff, u32 len);
- void sgm42406_fault_reg_reset(void);
- void set_clk_sta(u8 sta);
- void set_din_sta(u8 sta);
- void set_latch_sta(u8 sta);
- extern u8 get_nfault_sta(void);
- sgm42406_driver_t get_sgm42406_dev_handle(void);
- #endif /* __SGM42406_H__ */
其中源文件的主要代码如下所示,主要包括芯片初始化接口、回调函数实现接口、写数据接口和读故障寄存器数据接口等: - #include "sgm42406.h"
- sgm42406_driver sgm42406_dev0;
- void set_clk_sta(u8 sta)
- {
- switch(sta)
- {
- case 1:
- SGM42406_CLK_HIGH();
- break;
- case 0:
- SGM42406_CLK_LOW();
- break;
- }
- }
- void set_din_sta(u8 sta)
- {
- switch(sta)
- {
- case 1:
- SGM42406_DIN_HIGH();
- break;
- case 0:
- SGM42406_DIN_LOW();
- break;
- }
- }
- void set_latch_sta(u8 sta)
- {
- switch(sta)
- {
- case 1:
- SGM42406_LATCH_HIGH();
- break;
- case 0:
- SGM42406_LATCH_LOW();
- break;
- }
- }
- void set_enable_sta(u8 sta)
- {
- switch(sta)
- {
- case 1:
- SGM42406_EN_HIGH();
- break;
- case 0:
- SGM42406_EN_LOW();
- break;
- }
- }
- u8 get_dout_sta(void)
- {
- return SGM42406_READ_DOUT();
- }
- u8 get_nfault_sta(void)
- {
- return SGM42406_READ_FAULT();
- }
- void sgm42406_delay(u32 us)
- {
- u32 j = 0;
- //while(us--)
- {
- for(j = 0; j < us; j++)
- {
- __asm("nop");
- }
- }
- }
- /**
- * [url=/u/brief]@brief[/url] 娉ㄥ唽sgm42406璁惧
- *
- */
- static void sgm42406_register(void)
- {
- sgm42406_dev0.set_CLK_pin_sta = set_clk_sta;
- sgm42406_dev0.set_DIN_pin_sta = set_din_sta;
- sgm42406_dev0.set_LATCH_pin_sta = set_latch_sta;
- #ifdef SGM42406_A
- sgm42406_dev0.set_ENABLE_pin_sta = set_pin_sta;
- #elif defined(SGM42406_B)
- sgm42406_dev0.set_NENABLE_pin_sta = set_enable_sta;
- #endif
- sgm42406_dev0.get_DOUT_pin_sta = get_dout_sta;
- sgm42406_dev0.get_NFAULT_pin_sta = get_nfault_sta;
- sgm42406_dev0.sgm42406_delay_us = sgm42406_delay;
- }
- /**
- * @brief Get the sgm42406 dev handle object
- *
- * [url=/u/return]@return[/url] sgm42406_driver_t
- */
- sgm42406_driver_t get_sgm42406_dev_handle(void)
- {
- return &sgm42406_dev0;
- }
- void sgm42406_init(void)
- {
- sgm42406_driver_t pd;
- sgm42406_register();
- pd = get_sgm42406_dev_handle();
- pd->set_NENABLE_pin_sta(SGM42406_L);
- pd->set_LATCH_pin_sta(SGM42406_H);
- pd->set_CLK_pin_sta(SGM42406_H);
- pd->set_DIN_pin_sta(SGM42406_L);
- }
- void sgm42406_command_clk(u8 clk_times)
- {
- sgm42406_driver_t pd;
- int i = 0;
- pd = get_sgm42406_dev_handle();
- pd->set_LATCH_pin_sta(SGM42406_L);
- pd->set_CLK_pin_sta(SGM42406_L);
- pd->sgm42406_delay_us(1);
- for(i = 0; i < clk_times; i++)
- {
- pd->set_CLK_pin_sta(SGM42406_H);
- pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
- pd->set_CLK_pin_sta(SGM42406_L);
- pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
- }
- pd->set_LATCH_pin_sta(SGM42406_H);
- pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
- }
- /**
- * @brief 杈撳嚭闀垮害涓簂en鐨勬暟鎹?
- *
- * @param buff 瑕佽緭鍑烘暟鎹殑鍦板潃
- * @param len 杈撳嚭鐨勫瓧鑺傛暟
- * @return int8_t 鎴愬姛0锛屽け璐?1
- */
- s8 sgm42406_write_data(u8 *write_buff, u32 len)
- {
- sgm42406_driver_t pd;
- u8 send_data = 0;
- int i = 0;
- int j = 0;
- pd = get_sgm42406_dev_handle();
- pd->set_LATCH_pin_sta(SGM42406_L);
- for(i = len; i > 0; i--) //SGM42406鑺墖涓暟
- {
- send_data = write_buff[i-1]; //涓轰粈涔堣鍏堝啓鏈€鍚庝竴涓猙uff鏁版嵁锛?
- for(j = 0; j < 8; j++) //鍐?bit鏁版嵁
- {
- pd->set_CLK_pin_sta(SGM42406_L);
- if((send_data << j) & 0x80)
- {
- pd->set_DIN_pin_sta(SGM42406_H);
- }
- else
- {
- pd->set_DIN_pin_sta(SGM42406_L);
- }
- pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
- pd->set_CLK_pin_sta(SGM42406_H);
- pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
- }
- pd->set_DIN_pin_sta(SGM42406_L);
- pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
- pd->set_CLK_pin_sta(SGM42406_H);
- }
- pd->set_LATCH_pin_sta(SGM42406_H);
- return 0;
- }
- /*璇诲彇 16浣嶆晠闅滃瘎瀛樺櫒 锛岃鎺ュ彛闇€瑕佷慨鏀?/
- void sgm42406_read_fault_reg(u16 *read_buff, u8 chip_sum)
- {
- sgm42406_driver_t pd;
- //u16 *pread = read_buff;
- u16 read_data = 0;
- int i = 0;
- int j = 0;
- pd = get_sgm42406_dev_handle();
- #if 0
- pd->sgm42406_delay_us(500);
- pd->set_LATCH_pin_sta(SGM42406_H);
- pd->set_CLK_pin_sta(SGM42406_H);
- pd->sgm42406_delay_us(2);
- pd->set_CLK_pin_sta(SGM42406_L);
- pd->set_LATCH_pin_sta(SGM42406_L);
- pd->sgm42406_delay_us(5);
- pd->set_LATCH_pin_sta(SGM42406_H);
- pd->sgm42406_delay_us(5);
- #else
- pd->set_CLK_pin_sta(SGM42406_H);
- pd->set_LATCH_pin_sta(SGM42406_H);
- pd->sgm42406_delay_us(5);
- pd->set_CLK_pin_sta(SGM42406_L);
- pd->sgm42406_delay_us(5);
- pd->set_LATCH_pin_sta(SGM42406_L);
- pd->sgm42406_delay_us(5);
- pd->set_LATCH_pin_sta(SGM42406_H);
- pd->sgm42406_delay_us(5);
- pd->set_CLK_pin_sta(SGM42406_H);
- #endif
- for(i = 0; i < chip_sum; i++)
- {
- for(j = 0; j < 16; j++)
- {
- pd->set_CLK_pin_sta(SGM42406_H);
- pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
- pd->set_CLK_pin_sta(SGM42406_L);
- //pd->sgm42406_delay_us(2);
- read_data |= (pd->get_DOUT_pin_sta() << (15-j)); //鍏堣鏈€楂樹綅
- pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
- }
- //memcpy(&pread[i], &read_data, 2);
- read_buff[i] = read_data;
- read_data = 0;
- }
- //pd->sgm42406_delay_us(500);
- }
- void sgm42406_write_control_reg(u8 *write_buff, u32 len)
- {
- sgm42406_driver_t pd;
- pd = get_sgm42406_dev_handle();
- pd->set_LATCH_pin_sta(SGM42406_H);
- pd->set_CLK_pin_sta(SGM42406_H);
- pd->sgm42406_delay_us(2);
- pd->set_CLK_pin_sta(SGM42406_L);
- // pd->sgm42406_delay_us(2);
- sgm42406_command_clk(1);
- sgm42406_command_clk(2);
- sgm42406_command_clk(2);
- sgm42406_command_clk(3);
- sgm42406_write_data(write_buff, len);
- }
- void sgm42406_read_control_or_data_reg(sgm42406_read_reg_e reg, u8 *read_buff, u32 len)
- {
- sgm42406_driver_t pd;
- u8 *pread = read_buff;
- u8 read_data = 0;
- int i = 0;
- int j = 0;
- pd = get_sgm42406_dev_handle();
- pd->set_CLK_pin_sta(SGM42406_L);
- switch(reg)
- {
- case SGM42406_READ_CONTORL_REG:
- sgm42406_command_clk(1);
- sgm42406_command_clk(4);
- sgm42406_command_clk(2);
- sgm42406_command_clk(3);
- break;
- case SGM42406_READ_DATA_REG:
- sgm42406_command_clk(1);
- sgm42406_command_clk(4);
- sgm42406_command_clk(4);
- sgm42406_command_clk(3);
- break;
- }
- for(i = 0; i < len; i++)
- {
- for(j = 0; j < 8; j++)
- {
- read_data |= (pd->get_DOUT_pin_sta() << j);
- pd->sgm42406_delay_us(2);
- pd->set_CLK_pin_sta(SGM42406_H);
- pd->sgm42406_delay_us(2);
- pd->set_CLK_pin_sta(SGM42406_L);
- pd->sgm42406_delay_us(1);
- }
- memcpy(&pread[i], &read_data, 1);
- read_data = 0;
- }
- }
- void sgm42406_fault_reg_reset(void)
- {
- sgm42406_driver_t pd;
- pd = get_sgm42406_dev_handle();
- pd->set_LATCH_pin_sta(SGM42406_H);
- pd->set_CLK_pin_sta(SGM42406_H);
- pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
- pd->set_CLK_pin_sta(SGM42406_L);
- pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
- sgm42406_command_clk(1);
- sgm42406_command_clk(2);
- sgm42406_command_clk(4);
- sgm42406_command_clk(3);
- pd->set_CLK_pin_sta(SGM42406_H);
- }
以上的对SGM42406的解读分享,给大家提供参考。
|