ch423s.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /**
  2. * @file ch423s.h
  3. * @brief
  4. * @author lch (lch_work@foxmail.com)
  5. * @version 1.0
  6. * @date 20251224
  7. *
  8. * @copyright Copyright (c) 2025 by OLE, All Rights Reserved.
  9. *
  10. * @par 修改日志:
  11. * <table>
  12. * <tr><th>Date <th>Version <th>Author <th>Description
  13. * <tr><td>20251224 <td>2.0 <td>test <td>内容
  14. * </table>
  15. */
  16. #ifdef IO_CHIP_CH423S
  17. #include <fcntl.h>
  18. #include <sys/ioctl.h>
  19. #include <linux/i2c.h>
  20. #include <linux/i2c-dev.h>
  21. #include <errno.h>
  22. #include "head.h"
  23. /* 设置系统参数命令 */
  24. #define CH423_SYS_CMD 0x48 // 设置系统参数命令,默认方式
  25. #define BIT_SLEEP 0x30 // 低功耗睡眠控制 0正常工作 1睡眠模式
  26. #define BIT_INTENS 0x20 // 动态显示驱动亮度控制
  27. #define BIT_OD_OE 0x10 // 输出引脚 OC15~OC0 开漏输出使能 0推挽输出低电平和高电平 1开漏输出低电平和不输出
  28. #define BIT_X_INT 0x08 // 使能输入电平变化中断 0禁止输入电平变化中断 为1并且DEC_H为0允许从OC15引脚输出电平变化中断
  29. #define BIT_DEC_H 0x04 // 控制开漏输出引脚高8位的片选译码 0通用输出 1分时显示扫描计数器译码后
  30. #define BIT_DEC_L 0x02 // 控制开漏输出引脚低8位的片选译码 0通用输出 1分时显示扫描计数器译码后
  31. #define BIT_IO_OE 0x01 // 控制双向输入输出引脚的三态输出 0禁止输出 1允许输出
  32. /* 设置低8位开漏输出命令 */
  33. #define CH423_OC_L_CMD 0x44 // 设置低8位开漏输出命令,默认方式
  34. #define BIT_OC0_L_DAT 0x01 // OC0为0则使引脚输出低电平,为1则引脚不输出
  35. #define BIT_OC1_L_DAT 0x02 // OC1为0则使引脚输出低电平,为1则引脚不输出
  36. #define BIT_OC2_L_DAT 0x04 // OC2为0则使引脚输出低电平,为1则引脚不输出
  37. #define BIT_OC3_L_DAT 0x08 // OC3为0则使引脚输出低电平,为1则引脚不输出
  38. #define BIT_OC4_L_DAT 0x10 // OC4为0则使引脚输出低电平,为1则引脚不输出
  39. #define BIT_OC5_L_DAT 0x20 // OC5为0则使引脚输出低电平,为1则引脚不输出
  40. #define BIT_OC6_L_DAT 0x40 // OC6为0则使引脚输出低电平,为1则引脚不输出
  41. #define BIT_OC7_L_DAT 0x80 // OC7为0则使引脚输出低电平,为1则引脚不输出
  42. /* 设置高8位开漏输出命令 */
  43. #define CH423_OC_H_CMD 0x46 // 设置低8位开漏输出命令,默认方式
  44. #define BIT_OC8_L_DAT 0x01 // OC8为0则使引脚输出低电平,为1则引脚不输出
  45. #define BIT_OC9_L_DAT 0x02 // OC9为0则使引脚输出低电平,为1则引脚不输出
  46. #define BIT_OC10_L_DAT 0x04 // OC10为0则使引脚输出低电平,为1则引脚不输出
  47. #define BIT_OC11_L_DAT 0x08 // OC11为0则使引脚输出低电平,为1则引脚不输出
  48. #define BIT_OC12_L_DAT 0x10 // OC12为0则使引脚输出低电平,为1则引脚不输出
  49. #define BIT_OC13_L_DAT 0x20 // OC13为0则使引脚输出低电平,为1则引脚不输出
  50. #define BIT_OC14_L_DAT 0x40 // OC14为0则使引脚输出低电平,为1则引脚不输出
  51. #define BIT_OC15_L_DAT 0x80 // OC15为0则使引脚输出低电平,为1则引脚不输出
  52. /* 设置双向输入输出命令 */
  53. #define CH423_SET_IO_CMD 0x60 // 设置双向输入输出命令,默认方式
  54. #define BIT_IO0_DAT 0x01 // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO0为0输出低电平,为1输出高电平
  55. #define BIT_IO1_DAT 0x02 // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO1为0输出低电平,为1输出高电平
  56. #define BIT_IO2_DAT 0x04 // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO2为0输出低电平,为1输出高电平
  57. #define BIT_IO3_DAT 0x08 // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO3为0输出低电平,为1输出高电平
  58. #define BIT_IO4_DAT 0x10 // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO4为0输出低电平,为1输出高电平
  59. #define BIT_IO5_DAT 0x20 // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO5为0输出低电平,为1输出高电平
  60. #define BIT_IO6_DAT 0x40 // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO6为0输出低电平,为1输出高电平
  61. #define BIT_IO7_DAT 0x80 // 写入双向输入输出引脚的输出寄存器,当IO_OE=1,IO7为0输出低电平,为1输出高电平
  62. struct t_dev_cfg
  63. {
  64. uint8_t uc_port;
  65. uint8_t uc_pin;
  66. };
  67. struct t_dev_cfg t_ch423_gpio[] =
  68. {
  69. {CH423_OC_L_CMD, 0},
  70. {CH423_OC_L_CMD, 1},
  71. {CH423_OC_L_CMD, 2},
  72. {CH423_OC_L_CMD, 3},
  73. {CH423_OC_L_CMD, 4},
  74. {CH423_OC_L_CMD, 5},
  75. {CH423_OC_L_CMD, 6},
  76. {CH423_OC_L_CMD, 7},
  77. {CH423_OC_H_CMD, 8},
  78. {CH423_OC_H_CMD, 9},
  79. {CH423_OC_H_CMD, 10},
  80. {CH423_OC_H_CMD, 11},
  81. {CH423_OC_H_CMD, 12},
  82. {CH423_OC_H_CMD, 13},
  83. {CH423_OC_H_CMD, 14},
  84. {CH423_OC_H_CMD, 15},
  85. {CH423_SET_IO_CMD, 16},
  86. {CH423_SET_IO_CMD, 17},
  87. {CH423_SET_IO_CMD, 18},
  88. {CH423_SET_IO_CMD, 19},
  89. {CH423_SET_IO_CMD, 20},
  90. {CH423_SET_IO_CMD, 21},
  91. {CH423_SET_IO_CMD, 22},
  92. {CH423_SET_IO_CMD, 23},
  93. };
  94. #define I2C_DEV "/dev/i2c-5"
  95. static int sl_ch423s_fd = -1, sl_ch423s_init = -1;
  96. static uint32_t sul_io_status = 0;
  97. static unsigned long mtll_updata_ch423s_timer = 0;
  98. /**
  99. * @brief
  100. * @author lch (lch_work@foxmail.com)
  101. * @version 1.0
  102. * @date 20251224
  103. * @param[in/out] {uint8_t} _uc_cmd 命令
  104. * @param[in/out] {uint8_t} _uc_state 状态
  105. * @return * int
  106. * @retval none
  107. *
  108. * @warning none
  109. * @note none
  110. */
  111. static int ch423_write_data(uint8_t _uc_cmd, uint8_t _uc_state)
  112. {
  113. uint8_t uca_data[2] = {0};
  114. uca_data[0] = _uc_cmd;
  115. uca_data[1] = _uc_state;
  116. if (write(sl_ch423s_fd, &uca_data[0], 2) != 2)
  117. {
  118. dp_err_n_c_rt("Failed to send init command: %s", strerror(errno));
  119. return -1;
  120. }
  121. return 0;
  122. }
  123. /**
  124. * @brief
  125. * @author lch (lch_work@foxmail.com)
  126. * @version 1.0
  127. * @date 20251224
  128. * @param[in/out] {uint8_t} _uc_idx
  129. * @param[in/out] {uint8_t} _uc_state
  130. * @return * void
  131. * @retval none
  132. *
  133. * @warning none
  134. * @note none
  135. */
  136. static void ch423s_updata_port_status(uint8_t _uc_idx, uint8_t _uc_state)
  137. {
  138. /* 清除原始状态 */
  139. if ((sul_io_status >> _uc_idx) & 0x01)
  140. {
  141. sul_io_status ^= (1 << _uc_idx);
  142. }
  143. /* 重新设置 */
  144. sul_io_status |= _uc_state ? (0 << _uc_idx) : (1 << _uc_idx);
  145. }
  146. /**
  147. * @brief 定时更新gpio状态
  148. * @author lch (lch_work@foxmail.com)
  149. * @version 1.0
  150. * @date 20251224
  151. * @return * int
  152. * @retval none
  153. *
  154. * @warning none
  155. * @note none
  156. */
  157. int ch423sio_updata_status_ontime(void)
  158. {
  159. uint8_t uca_state[3] = {0};
  160. int l_ret = 0;
  161. if (bsp_ustimer_get_duration(mtll_updata_ch423s_timer) < (USTIMER_MS * 50) || sl_ch423s_fd < 0)
  162. {
  163. return -1;
  164. }
  165. mtll_updata_ch423s_timer = bsp_ustimer_get_origin();
  166. uca_state[0] = (uint8_t)(sul_io_status & 0xff);
  167. (0 = ch423_write_data(CH423_OC_L_CMD, uca_state[0])) ? l_ret : l_ret--;
  168. uca_state[1] = (uint8_t)((sul_io_status >> 8) & 0xff);
  169. (0 = ch423_write_data(CH423_OC_H_CMD, uca_state[1])) ? l_ret : l_ret--;
  170. uca_state[2] = (uint8_t)((sul_io_status >> 16) & 0xff);
  171. (0 = ch423_write_data(CH423_SET_IO_CMD, uca_state[2])) ? l_ret : l_ret--;
  172. return l_ret;
  173. }
  174. /**
  175. * @brief 设置io状态
  176. * @author lch (lch_work@foxmail.com)
  177. * @version 1.0
  178. * @date 20251224
  179. * @param[in/out] {uint8_t} _uc_idx 下标
  180. * @param[in/out] {uint8_t} _uc_state 电平状态
  181. * @return * int
  182. * @retval none
  183. *
  184. * @warning none
  185. * @note none
  186. */
  187. int ch423sio_set_io(uint8_t _uc_idx, uint8_t _uc_state)
  188. {
  189. uint8_t uc_num = sizeof(t_ch423_gpio) / sizeof(struct t_dev_cfg);
  190. if (_uc_idx >= uc_num || sl_ch423s_init < 0 || _uc_state > 1)
  191. {
  192. return -1;
  193. }
  194. switch (t_ch423_gpio[_uc_idx].uc_port)
  195. {
  196. case CH423_OC_L_CMD:
  197. ch423s_updata_port_status(t_ch423_gpio[_uc_idx].uc_pin, _uc_state);
  198. break;
  199. case CH423_OC_H_CMD:
  200. ch423s_updata_port_status(t_ch423_gpio[_uc_idx].uc_pin, _uc_state);
  201. break;
  202. case CH423_SET_IO_CMD:
  203. ch423s_updata_port_status(t_ch423_gpio[_uc_idx].uc_pin, _uc_state);
  204. break;
  205. default:
  206. return -2;
  207. break;
  208. }
  209. return 0;
  210. }
  211. /**
  212. * @brief 初始化设备
  213. * @author lch (lch_work@foxmail.com)
  214. * @version 1.0
  215. * @date 20251224
  216. * @return * int
  217. * @retval none
  218. *
  219. * @warning none
  220. * @note none
  221. */
  222. int ch423sio_init_dev(void)
  223. {
  224. // 打开I2C设备
  225. sl_ch423s_fd = open(I2C_DEV, O_RDWR);
  226. if (sl_ch423s_fd < 0)
  227. {
  228. dp_err_n_c_rt("Failed to open I2C device %s: %s", I2C_DEV, strerror(errno));
  229. return -1;
  230. }
  231. ch423_write_data(CH423_SYS_CMD, BIT_IO_OE); /* 将IO7~IO0设置为输出 其它参数使用默认值 */
  232. ch423_write_data(CH423_OC_L_CMD, 0xff);
  233. ch423_write_data(CH423_OC_H_CMD, 0xff);
  234. ch423_write_data(CH423_SET_IO_CMD, 0xff);
  235. sl_ch423s_init = 0;
  236. return 0;
  237. }
  238. /**
  239. * @brief 关闭句柄
  240. * @author lch (lch_work@foxmail.com)
  241. * @version 1.0
  242. * @date 20251224
  243. * @return * int
  244. * @retval none
  245. *
  246. * @warning none
  247. * @note none
  248. */
  249. int ch423sio_exit_dev(void)
  250. {
  251. if (sl_ch423s_fd >= 0)
  252. {
  253. close(sl_ch423s_fd);
  254. sl_ch423s_fd = -1;
  255. }
  256. return 0;
  257. }
  258. #endif /* TMP_CHIP_AHT20 */