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
链接:https://bbs.21ic.com/icview-3495603-1-1.html?_dsign=4ba244d0
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐