[资料干货] 八通道低侧驱动芯片SGM42406的使用分享

[复制链接]
825|2
dffzh 发表于 2025-11-12 16:30 | 显示全部楼层 |阅读模式
#申请原创#


@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的驱动代码:
  1. #ifndef __SGM42406_H__
  2. #define __SGM42406_H__

  3. #include "at32f403a_407.h"
  4. #include <string.h>

  5. #define  SGM42406_EN_GPIO     GPIOB
  6. #define  SGM42406_CLK_GPIO    GPIOB
  7. #define  SGM42406_LATCH_GPIO  GPIOA  
  8. #define  SGM42406_DIN_GPIO    GPIOB
  9. #define  SGM42406_FAULT_GPIO  GPIOA
  10. #define  SGM42406_DOUT_GPIO   GPIOB


  11. #define  SGM42406_EN_PIN          GPIO_PINS_2
  12. #define  SGM42406_CLK_PIN          GPIO_PINS_7
  13. #define  SGM42406_LATCH_GPIN  GPIO_PINS_4 // NSS pin
  14. #define  SGM42406_DIN_PIN          GPIO_PINS_9
  15. #define  SGM42406_FAULT_PIN          GPIO_PINS_8
  16. #define  SGM42406_DOUT_PIN          GPIO_PINS_8


  17. #define SGM42406_CLK_HIGH()  gpio_bits_write(SGM42406_CLK_GPIO, SGM42406_CLK_PIN, TRUE)
  18. #define SGM42406_CLK_LOW()   gpio_bits_write(SGM42406_CLK_GPIO, SGM42406_CLK_PIN, FALSE)

  19. #define SGM42406_LATCH_HIGH()  gpio_bits_write(SGM42406_LATCH_GPIO, SGM42406_LATCH_GPIN, TRUE)
  20. #define SGM42406_LATCH_LOW()   gpio_bits_write(SGM42406_LATCH_GPIO, SGM42406_LATCH_GPIN, FALSE)

  21. #define SGM42406_EN_HIGH()  gpio_bits_write(SGM42406_EN_GPIO, SGM42406_EN_PIN, TRUE)
  22. #define SGM42406_EN_LOW()   gpio_bits_write(SGM42406_EN_GPIO, SGM42406_EN_PIN, FALSE)

  23. #define SGM42406_DIN_HIGH()  gpio_bits_write(SGM42406_DIN_GPIO, SGM42406_DIN_PIN, TRUE)
  24. #define SGM42406_DIN_LOW()   gpio_bits_write(SGM42406_DIN_GPIO, SGM42406_DIN_PIN, FALSE)

  25. #define SGM42406_READ_DOUT()   gpio_input_data_bit_read(SGM42406_DOUT_GPIO,SGM42406_DOUT_PIN)

  26. #define SGM42406_READ_FAULT()   gpio_input_data_bit_read(SGM42406_FAULT_GPIO,SGM42406_FAULT_PIN)

  27. #define SGM42406_DELAY_TIME  0  //4

  28. #define SGM42406_B

  29. typedef enum {
  30.     SGM42406_L = 0,
  31.     SGM42406_H,
  32. }sgm42406_pin_sta_e;

  33. typedef enum {
  34.     SGM42406_READ_CONTORL_REG = 0,
  35.     SGM42406_READ_DATA_REG,
  36. }sgm42406_read_reg_e;

  37. typedef struct {
  38.     void (* set_LATCH_pin_sta)(u8 status);
  39.     void (* set_CLK_pin_sta)(u8 status);
  40.     void (* set_DIN_pin_sta)(u8 status);
  41. #ifdef SGM42406_A
  42.     void (* set_ENABLE_pin_sta)(u8 status);
  43. #elif defined(SGM42406_B)
  44.     void (* set_NENABLE_pin_sta)(u8 status);
  45. #endif

  46.     u8 (* get_DOUT_pin_sta) (void);
  47.     u8 (* get_NFAULT_pin_sta) (void);

  48.     void (* sgm42406_delay_us) (u32 us);
  49. }sgm42406_driver, *sgm42406_driver_t;

  50. void sgm42406_init(void);
  51. void sgm42406_command_clk(u8 clk_times);
  52. s8 sgm42406_write_data(u8 *write_buff, u32 len);
  53. void sgm42406_read_fault_reg(u16 *read_buff, u8 chip_sum);
  54. void sgm42406_write_control_reg(u8 *write_buff, u32 len);
  55. void sgm42406_read_control_or_data_reg(sgm42406_read_reg_e reg, u8 *read_buff, u32 len);
  56. void sgm42406_fault_reg_reset(void);
  57. void set_clk_sta(u8 sta);
  58. void set_din_sta(u8 sta);
  59. void set_latch_sta(u8 sta);
  60. extern u8 get_nfault_sta(void);
  61. sgm42406_driver_t get_sgm42406_dev_handle(void);

  62. #endif /* __SGM42406_H__ */
其中源文件的主要代码如下所示,主要包括芯片初始化接口、回调函数实现接口、写数据接口和读故障寄存器数据接口等:
  1. #include "sgm42406.h"

  2. sgm42406_driver sgm42406_dev0;

  3. void set_clk_sta(u8 sta)
  4. {
  5.         switch(sta)
  6.         {
  7.         case 1:
  8.                 SGM42406_CLK_HIGH();
  9.                 break;

  10.         case 0:
  11.                 SGM42406_CLK_LOW();
  12.                 break;
  13.         }
  14. }

  15. void set_din_sta(u8 sta)
  16. {
  17.         switch(sta)
  18.         {
  19.         case 1:
  20.                 SGM42406_DIN_HIGH();
  21.                 break;

  22.         case 0:
  23.                 SGM42406_DIN_LOW();
  24.                 break;
  25.         }
  26. }


  27. void set_latch_sta(u8 sta)
  28. {
  29.         switch(sta)
  30.         {
  31.         case 1:
  32.                 SGM42406_LATCH_HIGH();
  33.                 break;

  34.         case 0:
  35.                 SGM42406_LATCH_LOW();
  36.                 break;
  37.         }
  38. }

  39. void set_enable_sta(u8 sta)
  40. {
  41.         switch(sta)
  42.         {
  43.         case 1:
  44.                 SGM42406_EN_HIGH();
  45.                 break;

  46.         case 0:
  47.                 SGM42406_EN_LOW();
  48.                 break;
  49.         }
  50. }

  51. u8 get_dout_sta(void)
  52. {
  53.         return SGM42406_READ_DOUT();
  54. }

  55. u8 get_nfault_sta(void)
  56. {
  57.         return SGM42406_READ_FAULT();
  58. }

  59. void sgm42406_delay(u32 us)
  60. {
  61.     u32 j = 0;

  62.         //while(us--)
  63.         {
  64.                 for(j = 0; j < us; j++)
  65.                 {
  66.                         __asm("nop");
  67.                 }
  68.         }
  69. }

  70. /**
  71. * [url=/u/brief]@brief[/url] 娉ㄥ唽sgm42406璁惧
  72. *
  73. */
  74. static void sgm42406_register(void)
  75. {

  76.     sgm42406_dev0.set_CLK_pin_sta = set_clk_sta;
  77.     sgm42406_dev0.set_DIN_pin_sta = set_din_sta;
  78.     sgm42406_dev0.set_LATCH_pin_sta = set_latch_sta;
  79. #ifdef SGM42406_A
  80.     sgm42406_dev0.set_ENABLE_pin_sta = set_pin_sta;
  81. #elif defined(SGM42406_B)
  82.     sgm42406_dev0.set_NENABLE_pin_sta = set_enable_sta;
  83. #endif

  84.     sgm42406_dev0.get_DOUT_pin_sta = get_dout_sta;
  85.     sgm42406_dev0.get_NFAULT_pin_sta = get_nfault_sta;

  86.     sgm42406_dev0.sgm42406_delay_us = sgm42406_delay;
  87. }

  88. /**
  89. * @brief Get the sgm42406 dev handle object
  90. *
  91. * [url=/u/return]@return[/url] sgm42406_driver_t
  92. */
  93. sgm42406_driver_t get_sgm42406_dev_handle(void)
  94. {
  95.     return &sgm42406_dev0;
  96. }

  97. void sgm42406_init(void)
  98. {
  99.     sgm42406_driver_t pd;

  100.     sgm42406_register();
  101.     pd = get_sgm42406_dev_handle();

  102.     pd->set_NENABLE_pin_sta(SGM42406_L);
  103.     pd->set_LATCH_pin_sta(SGM42406_H);
  104.     pd->set_CLK_pin_sta(SGM42406_H);

  105.     pd->set_DIN_pin_sta(SGM42406_L);
  106. }

  107. void sgm42406_command_clk(u8 clk_times)
  108. {
  109.     sgm42406_driver_t pd;
  110.         int i = 0;

  111.     pd = get_sgm42406_dev_handle();

  112.     pd->set_LATCH_pin_sta(SGM42406_L);
  113.     pd->set_CLK_pin_sta(SGM42406_L);
  114.     pd->sgm42406_delay_us(1);

  115.     for(i = 0; i < clk_times; i++)
  116.     {
  117.         pd->set_CLK_pin_sta(SGM42406_H);
  118.         pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
  119.         pd->set_CLK_pin_sta(SGM42406_L);
  120.         pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
  121.     }

  122.     pd->set_LATCH_pin_sta(SGM42406_H);
  123.         pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
  124. }

  125. /**
  126. * @brief 杈撳嚭闀垮害涓簂en鐨勬暟鎹?
  127. *
  128. * @param buff 瑕佽緭鍑烘暟鎹殑鍦板潃
  129. * @param len 杈撳嚭鐨勫瓧鑺傛暟
  130. * @return int8_t 鎴愬姛0锛屽け璐?1
  131. */
  132. s8 sgm42406_write_data(u8 *write_buff, u32 len)
  133. {
  134.     sgm42406_driver_t pd;
  135.     u8 send_data = 0;
  136.         int i = 0;
  137.         int j = 0;

  138.     pd = get_sgm42406_dev_handle();

  139.     pd->set_LATCH_pin_sta(SGM42406_L);

  140.     for(i = len; i > 0; i--) //SGM42406鑺墖涓暟
  141.     {
  142.         send_data = write_buff[i-1]; //涓轰粈涔堣鍏堝啓鏈€鍚庝竴涓猙uff鏁版嵁锛?
  143.         for(j = 0; j < 8; j++) //鍐?bit鏁版嵁
  144.         {
  145.             pd->set_CLK_pin_sta(SGM42406_L);
  146.             if((send_data << j) & 0x80)
  147.             {
  148.                 pd->set_DIN_pin_sta(SGM42406_H);
  149.             }
  150.             else
  151.             {
  152.                 pd->set_DIN_pin_sta(SGM42406_L);

  153.             }
  154.             pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
  155.             pd->set_CLK_pin_sta(SGM42406_H);
  156.             pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
  157.         }
  158.         pd->set_DIN_pin_sta(SGM42406_L);
  159.                 pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
  160.                 pd->set_CLK_pin_sta(SGM42406_H);
  161.     }

  162.     pd->set_LATCH_pin_sta(SGM42406_H);

  163.     return 0;
  164. }

  165. /*璇诲彇 16浣嶆晠闅滃瘎瀛樺櫒 锛岃鎺ュ彛闇€瑕佷慨鏀?/
  166. void sgm42406_read_fault_reg(u16 *read_buff, u8 chip_sum)
  167. {
  168.     sgm42406_driver_t pd;
  169.     //u16 *pread = read_buff;
  170.     u16 read_data = 0;
  171.         int i = 0;
  172.         int j = 0;

  173.     pd = get_sgm42406_dev_handle();

  174. #if 0
  175.     pd->sgm42406_delay_us(500);
  176.     pd->set_LATCH_pin_sta(SGM42406_H);
  177.     pd->set_CLK_pin_sta(SGM42406_H);
  178.     pd->sgm42406_delay_us(2);
  179.     pd->set_CLK_pin_sta(SGM42406_L);
  180.     pd->set_LATCH_pin_sta(SGM42406_L);
  181.     pd->sgm42406_delay_us(5);
  182.     pd->set_LATCH_pin_sta(SGM42406_H);
  183.     pd->sgm42406_delay_us(5);
  184. #else
  185.     pd->set_CLK_pin_sta(SGM42406_H);
  186.     pd->set_LATCH_pin_sta(SGM42406_H);
  187.     pd->sgm42406_delay_us(5);
  188.     pd->set_CLK_pin_sta(SGM42406_L);
  189.     pd->sgm42406_delay_us(5);
  190.     pd->set_LATCH_pin_sta(SGM42406_L);
  191.     pd->sgm42406_delay_us(5);
  192.     pd->set_LATCH_pin_sta(SGM42406_H);
  193.     pd->sgm42406_delay_us(5);
  194.     pd->set_CLK_pin_sta(SGM42406_H);
  195. #endif

  196.     for(i = 0; i < chip_sum; i++)
  197.     {
  198.         for(j = 0; j < 16; j++)
  199.         {
  200.             pd->set_CLK_pin_sta(SGM42406_H);
  201.             pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
  202.             pd->set_CLK_pin_sta(SGM42406_L);
  203.             //pd->sgm42406_delay_us(2);
  204.             read_data |= (pd->get_DOUT_pin_sta() << (15-j)); //鍏堣鏈€楂樹綅
  205.             pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
  206.         }
  207.         //memcpy(&pread[i], &read_data, 2);
  208.         read_buff[i] = read_data;
  209.         read_data = 0;
  210.     }
  211.     //pd->sgm42406_delay_us(500);
  212. }

  213. void sgm42406_write_control_reg(u8 *write_buff, u32 len)
  214. {
  215.     sgm42406_driver_t pd;

  216.     pd = get_sgm42406_dev_handle();

  217.     pd->set_LATCH_pin_sta(SGM42406_H);
  218.     pd->set_CLK_pin_sta(SGM42406_H);
  219.     pd->sgm42406_delay_us(2);
  220.     pd->set_CLK_pin_sta(SGM42406_L);
  221. //    pd->sgm42406_delay_us(2);

  222.     sgm42406_command_clk(1);
  223.     sgm42406_command_clk(2);
  224.     sgm42406_command_clk(2);
  225.     sgm42406_command_clk(3);

  226.     sgm42406_write_data(write_buff, len);
  227. }

  228. void sgm42406_read_control_or_data_reg(sgm42406_read_reg_e reg, u8 *read_buff, u32 len)
  229. {
  230.     sgm42406_driver_t pd;
  231.     u8 *pread = read_buff;
  232.     u8 read_data = 0;
  233.         int i = 0;
  234.         int j = 0;

  235.     pd = get_sgm42406_dev_handle();

  236.     pd->set_CLK_pin_sta(SGM42406_L);

  237.     switch(reg)
  238.     {
  239.         case SGM42406_READ_CONTORL_REG:
  240.             sgm42406_command_clk(1);
  241.             sgm42406_command_clk(4);
  242.             sgm42406_command_clk(2);
  243.             sgm42406_command_clk(3);
  244.             break;

  245.         case SGM42406_READ_DATA_REG:
  246.             sgm42406_command_clk(1);
  247.             sgm42406_command_clk(4);
  248.             sgm42406_command_clk(4);
  249.             sgm42406_command_clk(3);
  250.             break;
  251.     }

  252.     for(i = 0; i < len; i++)
  253.     {
  254.         for(j = 0; j < 8; j++)
  255.         {
  256.             read_data |= (pd->get_DOUT_pin_sta() << j);
  257.             pd->sgm42406_delay_us(2);
  258.             pd->set_CLK_pin_sta(SGM42406_H);
  259.             pd->sgm42406_delay_us(2);
  260.             pd->set_CLK_pin_sta(SGM42406_L);
  261.             pd->sgm42406_delay_us(1);
  262.         }
  263.         memcpy(&pread[i], &read_data, 1);
  264.         read_data = 0;
  265.     }
  266. }

  267. void sgm42406_fault_reg_reset(void)
  268. {
  269.     sgm42406_driver_t pd;

  270.     pd = get_sgm42406_dev_handle();

  271.     pd->set_LATCH_pin_sta(SGM42406_H);
  272.     pd->set_CLK_pin_sta(SGM42406_H);
  273.     pd->sgm42406_delay_us(SGM42406_DELAY_TIME);
  274.     pd->set_CLK_pin_sta(SGM42406_L);
  275.     pd->sgm42406_delay_us(SGM42406_DELAY_TIME);

  276.     sgm42406_command_clk(1);
  277.     sgm42406_command_clk(2);
  278.     sgm42406_command_clk(4);
  279.     sgm42406_command_clk(3);

  280.     pd->set_CLK_pin_sta(SGM42406_H);
  281. }
以上的对SGM42406的解读分享,给大家提供参考。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| dffzh 发表于 2025-11-12 16:32 | 显示全部楼层
#申请原创# @21小跑堂 管理员,你好,求原创审核哦!

MessageRing 发表于 2025-11-18 16:16 | 显示全部楼层
代码写的很详细
您需要登录后才可以回帖 登录 | 注册

本版积分规则

209

主题

1804

帖子

23

粉丝
快速回复 在线客服 返回列表 返回顶部
0