小言_互联网的博客

HaaS100 I2C使用之板上I2C MUXer

396人阅读  评论(0)

概述

本文主要介绍了HaaS100 I2C和I2C MUXer的硬件情况如何使用

 

适用范围

  • 希望了解和学习HaaS和I2C外设的爱好者
  • 希望使用HaaS I2C进行开发的开发人员

 

目标

  • 基于I2C完成板上I2C MUXer的初始化,通道设置和读取

 

所需工具

  • HaaS100                1块
  • 随附电源                1套
  • Micro USB线          1条
  • 串口终端(这里使用的是Xshell 6 (build 0206))                          

 

外设简介

I²CInter-Integrated Circuit)是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。I²C的正确读法为“I方C”。

I²C只使用两条双向漏极开路(Open Drain)(串行资料(SDA)及串行时脉(SCL))并利用电阻将电位上拉。

I²C的参考设计使用一个7位元长度的位址空间但保留了16个位址,所以在一组汇流排最多可和112个节点通讯[a]。常见的I²C汇流排依传输速率的不同而有不同的模式:标准模式(100 kbit/s)、低速模式(10 kbit/s),但时脉频率可被允许下降至零,这代表可以暂停通讯。而新一代的I²C汇流排可以和更多的节点(支援10位元长度的位址空间)以更快的速率通讯:快速模式(400 kbit/s)、快速+模式(1 Mbit/s)高速模式(3.4 Mbit/s)超高速模式(5 Mbit/s)。(以上摘自维基百科

以先为典型的I2C的总线连接图(图1):

图1 典型I2C总线连接

HaaS100的I2C情况

HaaS100使用的HaaS1000主控芯片支持2路I2C master,其中一路被UART2所复用连接到板上的扩展接口上,参考图2中黑色框中的Pin脚,暂时无法使用,为了有更多的I2C资源给到客户,我们使用了I2C MUXer将剩下的1路I2C扩展成了4路,其中两路已经在片上使用,另外两路连接到了扩展接口上,参考图2红色框中的Pin脚。

图2 HaaS扩展插槽

 

HaaS100板上的I2C连接,可以参考图3中高亮的部分,这些为I2C相关的扩展部分

图3 HaaS100 I2C扩展俯视图

 

HaaS100板上的I2C逻辑拓扑图如图4:

图4 HaaS100板上I2C逻辑拓扑图

 

I2C MUXer

HaaS100使用的是TI(德州仪器)的PCA9544A,是一个4 通道 I2C 和 SMBus 多路复用器,详细资料请参考官网

使用指南

1、使用前环境准备可参考开发环境安装,如下为实际操作用的环境,仅供参考

  • 本文所使用的系统为:UBuntu 16.04
  • aos cube版本:0.5.10
  • Python版本:3.5.2

2、本流程所涉及的相关文件:

I2C MUXer驱动

  • components/peripherals/i2c_muxer/pca9544.c
  • components/peripherals/i2c_muxer/pca9544.h

流程:

  • 相关宏,结构体介绍
  1. 
        
    1. /* ===== Default Configuration Based on BSP ===== */
    2. #ifdef HAAS_I2C
    3. #define I2C_PORT 1
    4. #define I2C_ADDR_W_8BIT 8
    5. #define I2C_BR_100K 100000
    6. #endif
    7. /* ===== MACRO Definition ===== */
    8. #define PCA9544_CHAN_CLEAN 0
    9. #define PCA9544_CONFIG_REG_LEN 1U
    10. #define PCA9544_IRQ_MASK 0xF0
    11. #define PCA9544_BASE_ADDR 0x70
    12. /* ===== Dev Type Definition ===== */
    13. /* pca9544 channel list */
    14. typedef enum
    15. {
    16. PCA9544_CH_NULL = 0,
    17. PCA9544_CHO = 4,
    18. PCA9544_CH1 = 5,
    19. PCA9544_CH2 = 6,
    20. PCA9544_CH3 = 7,
    21. }PCA9544_CH_E;
    22. /* pca9544 parameters configuration */
    23. typedef struct
    24. {
    25. /* pca9544 i2c address */
    26. uint8_t dev_addr;
    27. /* pca9544 interrupt status */
    28. uint8_t irq_status;
    29. /* the current pca9544 channel */
    30. PCA9544_CH_E pca9544_ch;
    31. /* the sub dev addr for the selected pca9544 channel */
    32. uint8_t subdev_addr;
    33. //uint8_t control_reg;
    34. /* the sub dev register address */
    35. uint8_t reg_addr;
    36. }PCA9544_DEV_CFG_T;

    PCA9544有四个可选通道,原始选通值为4/5/6/7,这里已经使用枚举做了封装;

    PCA9544的I2C Address通过硬件做了相关配置,这里是0x70;

    详见components/peripherals/i2c_muxer/pca9544.h

  • 初始化

  
  1. i2c_dev_t i2c;
  2. PCA9544_DEV_CFG_T dev_cfg;
  3. dev_cfg.dev_addr = PCA9544_BASE_ADDR;
  4. dev_cfg.pca9544_ch = test_chan;
  5. dev_cfg.subdev_addr = 0x32;
  6. dev_cfg.reg_addr = 0x10;
  7. i2c.port = 1;
  8. i2c.config.address_width = 8;
  9. i2c.config.freq = I2C_BUS_BIT_RATES_100K;
  10. i2c.config.dev_addr = dev_cfg.dev_addr;
  11. /* I2C Initialization */
  12. ret = hal_i2c_init(&i2c);
  13. if (ret) {
  14. printf( "=====i2c test : i2c 1 dev init fail =====\r\n");
  15. return -1;
  16. }
  17. /* I2C MUXer PCA9544 Initialization */
  18. ret = pca9544_init(&i2c, &dev_cfg);
  19. if (ret) {
  20. printf( "=====pca9544 test : init fail =====\r\n");
  21. return -1;
  22. }
  • PCA9544初始化的具体实现:

  
  1. /**********************************************************
  2. * @fun PCA9544_init
  3. * @breif pca9544 initialization
  4. * @param i2c:the pointer for i2c configuration
  5. * @param dev_cfg: the pointer for dev configuration
  6. * @rtn
  7. *********************************************************/
  8. int pca9544_init(i2c_dev_t *i2c, PCA9544_DEV_CFG_T* dev_cfg)
  9. {
  10. int ret = 0;
  11. if(i2c == NULL)
  12. {
  13. printf( "PCA9544 i2c is null\n");
  14. return -1;
  15. }
  16. memset(&g_pca9544_i2c_cfg, 0, sizeof( i2c_dev_t));
  17. memcpy(&g_pca9544_i2c_cfg, i2c, sizeof( i2c_dev_t));
  18. ret = hal_i2c_init(&g_pca9544_i2c_cfg);
  19. if(ret)
  20. {
  21. printf( "Host I2C open failed\n");
  22. hal_i2c_finalize(&g_pca9544_i2c_cfg);
  23. return -1;
  24. }
  25. if(dev_cfg == NULL)
  26. {
  27. printf( "PCA9544 cfg is null\n");
  28. return -1;
  29. }
  30. memset(&g_pca9544_dev_cfg, 0, sizeof(PCA9544_DEV_CFG_T));
  31. memcpy(&g_pca9544_dev_cfg, dev_cfg, sizeof(PCA9544_DEV_CFG_T));
  32. printf( "PCA9544 cfg is successful\n");
  33. return ret;
  34. }
  • PCA9544的寄存器配置,这里是进行通道选择配置:

  
  1. /* chan select */
  2. printf( "=====i2c test : set chan 2[%d] of PCA9544=====\r\n", test_chan);
  3. ret = pca9544_set_chan(test_chan);
  4. osDelay( 2);
  5. read_chan = pca9544_read_chan();
  6. printf( "=====I2C Muxer test : read chan val of PCA9544 is %d=====\r\n", read_chan);
  • 至此PCA9544的通道选通已经完成,下面进行回读验证:

  
  1. osDelay( 2);
  2. /*if((reg & reg_rtn) == reg)*/
  3. if(test_chan == read_chan)
  4. {
  5. printf( "=====I2C Muxer test : PCA9544 test: PASS=====\r\n");
  6. }
  7. else
  8. {
  9. printf( "=====I2C Muxer test : PCA9544 test: FAIL=====\r\n");
  10. ret = -1;
  11. }

如果回读值等于预设值则配置成功,反之则反。

 

实际测试

  • 整体测试代码,可以基于helloworld_demo做修改,具体位置application/example/helloworld_demo/appdemo.c

完成测试代码如下


  
  1. /*
  2. * Copyright (C) 2015-2020 Alibaba Group Holding Limited
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <aos/errno.h>
  7. #include <aos/kernel.h>
  8. #include "aos/init.h"
  9. #include "board.h"
  10. #include <k_api.h>
  11. #include "pca9544.h"
  12. #include "aos/hal/i2c.h"
  13. static int32_t i2c_test_process()
  14. {
  15. int32_t ret;
  16. char data[ 7] = { 0x01, 1, 1, 1, 7, 9, 20};
  17. char data_rtn[ 7] = { 0};
  18. uint16_t size = 7;
  19. PCA9544_CH_E test_chan = PCA9544_CH1;
  20. PCA9544_CH_E read_chan = PCA9544_CH_NULL;
  21. uint8_t reg_rtn;
  22. uint8_t chan_mask = 0x05;
  23. i2c_dev_t i2c;
  24. PCA9544_DEV_CFG_T dev_cfg;
  25. dev_cfg.dev_addr = PCA9544_BASE_ADDR;
  26. dev_cfg.pca9544_ch = test_chan;
  27. dev_cfg.subdev_addr = 0x32;
  28. dev_cfg.reg_addr = 0x10;
  29. i2c.port = 1;
  30. i2c.config.address_width = 8;
  31. i2c.config.freq = I2C_BUS_BIT_RATES_100K;
  32. i2c.config.dev_addr = dev_cfg.dev_addr;
  33. ret = hal_i2c_init(&i2c);
  34. if (ret) {
  35. printf( "=====i2c test : i2c 1 dev init fail =====\r\n");
  36. return -1;
  37. }
  38. ret = pca9544_init(&i2c, &dev_cfg);
  39. if (ret) {
  40. printf( "=====pca9544 test : init fail =====\r\n");
  41. return -1;
  42. }
  43. /* chan select */
  44. printf( "=====i2c test : set chan 2[%d] of PCA9544=====\r\n", test_chan);
  45. ret = pca9544_set_chan(test_chan);
  46. osDelay( 2);
  47. read_chan = pca9544_read_chan();
  48. printf( "=====I2C Muxer test : read chan val of PCA9544 is %d=====\r\n", read_chan);
  49. osDelay( 2);
  50. /*if((reg & reg_rtn) == reg)*/
  51. if(test_chan == read_chan)
  52. {
  53. printf( "=====I2C Muxer test : PCA9544 test: PASS=====\r\n");
  54. }
  55. else
  56. {
  57. printf( "=====I2C Muxer test : PCA9544 test: FAIL=====\r\n");
  58. ret = -1;
  59. }
  60. hal_i2c_finalize(&i2c);
  61. return 0;
  62. }
  63. static int i2c_autotest()
  64. {
  65. int32_t ret = 0;
  66. printf( "\r\n\r\n");
  67. printf( "***************************************************************\r\n");
  68. printf( "*************************** I2C&RTC Test **********************\r\n");
  69. printf( "***************************************************************\r\n");
  70. printf( "** Note: this test don't need to connect any external tool **\r\n");
  71. printf( "** How to test: this test is a autotest **\r\n");
  72. printf( "** Process 1.1 set chan1(0x05) for PCA9544 by i2c **\r\n");
  73. printf( "** Process 1.2 read_chan the selected chan no. from PCA9544 **\r\n");
  74. printf( "** Process 2.1 set 20.9.7 1:1:1 to RX8310CE **\r\n");
  75. printf( "** Process 2.2 read the current time from RX8310CE **\r\n");
  76. printf( "***************************************************************\r\n");
  77. printf( "=====i2c test : Start=====\r\n");
  78. ret = i2c_test_process();
  79. if(ret)
  80. {
  81. printf( "\r\n=====i2c test : FAIL ===\r\n");
  82. return -1;
  83. }
  84. printf( "\r\n=====i2c test : PASS===\r\n");
  85. return 0;
  86. }
  87. int application_start(int argc, char *argv[])
  88. {
  89. int count = 0;
  90. printf( "nano entry here!\r\n");
  91. i2c_autotest();
  92. while( 1) {
  93. printf( "hello world! count %d \r\n", count++);
  94. aos_msleep( 1000);
  95. };
  96. }
  • 连接HaaS100电源,电源指示灯亮
  • 编译代码:

  
  1. aos make disclean
  2. aos make clean
  3. aos make helloworld_demo@haas100 -c config && aos make

注意:前两步是为了清理干净环境,避免引入其他问题

  • 编译结果:部分

  
  1. Making helloworld_demo@haas100.bin
  2. Making helloworld_demo@haas100.hex
  3. AOS MEMORY MAP
  4. |=================================================================|
  5. | MODULE | ROM | RAM |
  6. |=================================================================|
  7. | arch_armv7m | 2174 | 0 |
  8. | board_haas100 | 2212 | 6815812 |
  9. | cli | 6918 | 373 |
  10. | debug | 9696 | 132 |
  11. | helloworld_demo | 1807 | 12 |
  12. | i2c_muxer | 632 | 25 |
  13. | kernel_init | 359 | 12 |
  14. | kv | 3297 | 36 |
  15. | libc_nano | 20270 | 3911 |
  16. | libgcc | 3612 | 0 |
  17. | libhaas1000 | 597823 | 921102 |
  18. | libm | 18820 | 1594 |
  19. | lwip | 38935 | 3281 |
  20. | mcu_haas1000 | 33057 | 3206 |
  21. | newlib_stub | 614 | 0 |
  22. | osal_aos | 1096 | 0 |
  23. | osal_posix | 129 | 136 |
  24. | rhino | 13739 | 18262 |
  25. | ulog | 1519 | 331 |
  26. | vfs | 1092 | 1113 |
  27. | yloop | 1336 | 32 |
  28. | *fill* | 4978950 | 71513 |
  29. |=================================================================|
  30. | TOTAL (bytes) | 5738087 | 7840883 |
  31. |=================================================================|
  32. gen signature and release image ...
  33. OUTPUT_DIR is out/helloworld_demo@haas100
  34. format wrong
  35. /workspace/haas/test_senmu_0819/platform/mcu/haas1000/release/auto_build_tool
  36. [ 'chmod', '777', '/workspace/haas/test_senmu_0819/platform/mcu/haas1000/release/auto_build_tool/bes_sign_tool']
  37. Start chmod sign dir...
  38. chmod sign dir done.
  39. Start make littlefs
  40. Debug output enabled
  41. /demo
  42. file size: 21
  43. genfs done.
  44. Littlefs code size:4907008
  45. Make littlefs done
  46. cp -f ../../prebuild/factory.bin ../release_bin/
  47. cp -f ../../prebuild/littlefs.bin ../release_bin/
  48. cp -f ../../prebuild/data ../release_bin/
  49. cp -f ../../prebuild/pub_otp.bin ../release_bin/
  50. cp -f ../../prebuild/ota_boot2a.bin ../release_bin/
  51. cp -f ../../prebuild/boot_info.bin ../release_bin/
  52. cp -f ../../prebuild/ota_boot1.bin ../release_bin/
  53. cp -f ../../prebuild/ota_boot1_sec.bin ../release_bin/
  54. cp -f ../../prebuild/programmer2001.bin ../release_bin/
  55. cp /workspace/haas/test_senmu_0819/out/helloworld_demo@haas100/binary/*@haas100.bin ../release_bin/ota_rtos.bin
  56. /workspace/haas/test_senmu_0819/out/helloworld_demo@haas100/binary/helloworld_demo@haas100.bin
  57. cp -f ../write_flash_gui/dld_cfg/haas1000_dld_cfg.yaml ../write_flash_gui/
  58. cp -f ../write_flash_gui/haas1000_dld_cfg.yaml ../write_flash_gui/haas1000_dld_cfg.yaml
  59. cp -f ../release_bin/programmer2001.bin ../write_flash_tool/tools/
  60. cp -f ../release_bin/programmer2001.bin ../write_flash_gui/
  61. cp -f ../release_bin/factory.bin ../write_flash_tool/ota_bin/
  62. cp -f ../release_bin/factory.bin ../write_flash_gui/ota_bin/
  63. cp -f ../release_bin/littlefs.bin ../write_flash_tool/ota_bin/
  64. cp -f ../release_bin/littlefs.bin ../write_flash_gui/ota_bin/
  65. cp -f ../release_bin/ota_rtos.bin ../write_flash_tool/ota_bin/
  66. cp -f ../release_bin/ota_rtos.bin ../write_flash_gui/ota_bin/
  67. cp -f ../release_bin/pub_otp.bin ../write_flash_tool/ota_bin/
  68. cp -f ../release_bin/pub_otp.bin ../write_flash_gui/ota_bin/
  69. cp -f ../release_bin/ota_boot2a.bin ../write_flash_tool/ota_bin/
  70. cp -f ../release_bin/ota_boot2a.bin ../write_flash_gui/ota_bin/
  71. cp -f ../release_bin/boot_info.bin ../write_flash_tool/ota_bin/
  72. cp -f ../release_bin/boot_info.bin ../write_flash_gui/ota_bin/
  73. cp -f ../release_bin/ota_boot1.bin ../write_flash_tool/ota_bin/
  74. cp -f ../release_bin/ota_boot1.bin ../write_flash_gui/ota_bin/
  75. cp -f ../release_bin/ota_boot1_sec.bin ../write_flash_tool/ota_bin/
  76. cp -f ../release_bin/ota_boot1_sec.bin ../write_flash_gui/ota_bin/
  77. cp -f ../release_bin/ota_boot1_sec.bin ../write_flash_gui/ota_bin/
  78. all files done.
  79. gen ota image ...
  80. Build complete: helloworld_demo@haas100
  • 使用图形化烧录工具烧录固件:

固件位置:./platform/mcu/haas1000/release/write_flash_gui

如果之前烧录过,可以直接替换上述文件夹中的ota_bin/ota_rtos.bin文件

  • 烧录工具截图如下:

图5 HaaS100烧录截图

  • 烧录完成后停止烧录工具串口连接,使用Micro USB线连接HaaS100到PC,这里连接的是Win10环境,打开串口工具,做如下设置,串口号根据实际情况,波特率需要设置到1500000(五个0)

图6 HaaS100串口设置

  • 打开串口终端,并按下HaaS100重启键,打印出如下测试结果:

  
  1. ***************************************************************
  2. *************************** I2C&RTC Test **********************
  3. ***************************************************************
  4. ** Note: this test don 't need to connect any external tool **
  5. ** How to test: this test is a autotest **
  6. ** Process 1.1 set chan1(0x05) for PCA9544 by i2c **
  7. ** Process 1.2 read_chan the selected chan no. from PCA9544 **
  8. ** Process 2.1 set 20.9.7 1:1:1 to RX8310CE **
  9. ** Process 2.2 read the current time from RX8310CE **
  10. ***************************************************************
  11. =====i2c test : Start=====
  12. PCA9544 cfg is successful
  13. =====i2c test : set chan 2[5] of PCA9544=====
  14. =====I2C Muxer test : read chan val of PCA9544 is 5=====
  15. =====I2C Muxer test : PCA9544 test: PASS=====

至此HaaS100的I2C初始化和PCA9544的通道选通就已经完成。

 

结语

HaaS100的I2C涉及到的细节相对多一些,在后面的系列文章里会逐步给大家介绍清楚,下次会介绍mux_i2c的通用接口。

 

小结

如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号

更多技术与解决方案介绍,请访问阿里云AIoT首页https://iot.aliyun.com/


转载:https://blog.csdn.net/HaaSTech/article/details/112114152
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场