cruelfox 发表于 2021-6-30 23:04

RSL10的I2C操作与KX023加速度测量数据读取

本帖最后由 cruelfox 于 2021-7-2 20:48 编辑

<p>  RSL10的I2C接口访问,可以用SDK提供的API实现,当然也可以自己操作寄存器。</p>

<p>  SDK pack 里面的&nbsp;firmware/syslib 下面只提供了 include/rsl10_sys_i2c.h 头文件,定义了几个 inline 函数,可以看作是寄存器操作的快捷方式。并没有 rsl10_sys_i2c.c 文件,不足以进行完整的I2C读写流程。</p>

<p>  firmware/drivers/i2c_driver 目录下有 I2C_RSLxx.c 文件,实现了好多函数如 I2C_MasterTransmit() 这类的,还有 IRQHandler, DMA_Handler 支持函数。但是我发现代码不全,比如 ARM_DRIVER_I2C 这个类型没有定义,在 I2C_RSLxx.h 头文件中也没有。后来找到在背带裤(BDK)里面的 Driver_I2C.h 才有这个定义。因为依赖关系太复杂,我就不想用了,还是自己写寄存器操作吧。</p>

<p>  看起来也不复杂,I2C寄存器组的访问C语言写法和用STM32是差不多的。I2C的APB时钟默认已经开启了,可以直接操作I2C的CTRLx寄存器来开启 I2C 功能。I/O口的配置只需要借助头文件定义的一条函数 Sys_I2C_DIOConfig() 便可指定 SCL, SDA 两个信号各用哪个引脚,甚为方便。</p>

<p>  那么是用 PIO 方式,还是 IRQ 方式、DMA 方式进行数据传输呢?虽然 I2C 属于低速设备,但是 RSL10 的运行频率不高,I2C 在这里被我用在&nbsp;1MHz SCL 频率(线短,挂的设备少),每9个SCL时钟就中断一次,CPU空闲出来的周期也很有限。DMA方式好一些,但读 I2C 的时候程序也没有其它任务可以做,还是等着,短时间利用 WFI 省电也很有限。我就直接用 PIO 方式遍了,就是循环测试寄存器状态位。</p>

<p>  大部分 I2C 设备都是通过 写一个寄存器地址,再连续读或者写一连串数据的方式访问的。KX023 就属于这种,于是我实现两个函数分别用于 KX023 的访问。</p>

<pre>
<code class="language-cpp">int acc_write(uint8_t addr, const uint8_t *data, uint8_t len)
{
        int i;
        uint16_t s;
        I2C-&gt;ADDR_START = I2C_SlaveAddr&lt;&lt;I2C_ADDR_START_ADDRESS_Pos|I2C_START_WRITE;
        while(I2C-&gt;STATUS &amp; I2C_BUFFER_FULL)
        {        // Address buffered
        }
        // may write data here
        I2C-&gt;DATA = addr;        // first reg address
        while( (s=I2C-&gt;STATUS) &amp; I2C_BUFFER_FULL)
        {
                if(s &amp; I2C_HAS_NACK)        // cannot continue
                        return i;
        }
        for(i=0;i&lt;len;i++)
        {
                // buffer available
                I2C-&gt;DATA = data;
                while( (s=I2C-&gt;STATUS) &amp; I2C_BUFFER_FULL)
                {
                        if(s &amp; I2C_HAS_NACK)        // cannot continue
                                return i;
                }
                if(i==len-1)
                        I2C-&gt;CTRL1 = I2C_LAST_DATA;
        }
        while(!(I2C-&gt;STATUS &amp; I2C_BUS_FREE))
        {
        }
        return i;
}</code></pre>

<pre>
<code class="language-cpp">int acc_read(uint8_t addr, uint8_t *data, uint8_t len)
{
        int i;
        uint16_t s;
        I2C-&gt;ADDR_START = I2C_SlaveAddr&lt;&lt;I2C_ADDR_START_ADDRESS_Pos|I2C_START_WRITE;
        while(I2C-&gt;STATUS &amp; I2C_BUFFER_FULL)
        {        // Address buffered
        }
        // may write data here
        I2C-&gt;DATA = addr;        // first reg address
        while( (s=I2C-&gt;STATUS) &amp; I2C_BUFFER_FULL)
        {
                if(s &amp; I2C_HAS_NACK)        // cannot continue
                        return 0;
        }
        // repeated START, READ
        I2C-&gt;ADDR_START = I2C_SlaveAddr&lt;&lt;I2C_ADDR_START_ADDRESS_Pos|I2C_START_READ;
        while(I2C-&gt;STATUS &amp; I2C_BUFFER_FULL)
        {        // address buffered
        }
        for(i=0;i&lt;len;i++)
        {
                if(i==len-1)
                        I2C-&gt;CTRL1 = I2C_LAST_DATA;
                while(!((s=I2C-&gt;STATUS) &amp; I2C_BUFFER_FULL))
                {
                        if(s &amp; I2C_HAS_NACK)        // error
                                return i;
                }
                data=I2C-&gt;DATA;
        }
        return i;
}</code></pre>

<p>  每次从Sleep模式唤醒后,都需要重新初始化I2C接口硬件。</p>

<pre>
<code class="language-cpp">void i2c_initialize(void)
{
        Sys_I2C_DIOConfig(DIO_STRONG_PULL_UP, 1, 9);        // SCL on DIO7, SDA on DIO8
        I2C-&gt;CTRL0 = 1&lt;&lt;I2C_CTRL0_SPEED_Pos
                        |I2C_AUTO_ACK_ENABLE
                        |I2C_SAMPLE_CLK_ENABLE;
}</code></pre>

<p>&nbsp;</p>

<p>  在试验阶段,读取 KX023 的加速度数据可以用 RTT 打印出来,从 Segger RTT Viewer 软件中保存成日志文件。RTT比用UART速度快,而且不需要额外的连线。</p>

<p></p>

<p>  加速度计在一块PCB上(从手环电路板裁下来的),用橡皮泥粘在门上,采集门板的加速度。<i></i></p>

<p>  然后把数据整理一下,用GNU Octave (语法跟商业软件Matlab相似)读取,画图。</p>

<p></p>

<p><i><i>&nbsp;</i></i></p>

<p></p>

<p>  这是一些对门的&ldquo;动作&rdquo;的数据记录。</p>

dql2016 发表于 2021-7-1 12:13

<p>厉害,废物利用</p>

lightxixi 发表于 2021-7-1 15:12

<p>很详细,谢谢分享~</p>

okhxyyo 发表于 2021-7-1 17:08

<p>GNU Octave&nbsp; 这个是什么软件啊??matlab的替换软件吗?</p>

cruelfox 发表于 2021-7-2 20:52

okhxyyo 发表于 2021-7-1 17:08
GNU Octave&nbsp; 这个是什么软件啊??matlab的替换软件吗?

<p>不是替换软件。Matlab很庞大,Octave是个开源软件,功能没那么多,能支持一部分matlab的语法。</p>

okhxyyo 发表于 2021-7-5 09:31

cruelfox 发表于 2021-7-2 20:52
不是替换软件。Matlab很庞大,Octave是个开源软件,功能没那么多,能支持一部分matlab的语法。

<p>哦哦哦。这样呀,原来如此。什么时候能出来一个或一套的软件可以替代matlab呀</p>

freebsder 发表于 2021-7-6 22:23

<p>华健兄也是个&ldquo;折腾人&rdquo;哈哈,Octave,握手</p>
页: [1]
查看完整版本: RSL10的I2C操作与KX023加速度测量数据读取