龙芯1c库是把龙芯1c的常用外设的常用功能封装为一个库,类似于STM32库。Git地址:https://gitee.com/caogos/OpenLoongsonLib1c
龙芯1c库中模拟I2C接口使用示例
系统初始化时,首先调用simulate_i2c_init()对gpio初始化,然后调用simulate_i2c_start()发送I2C的开始信号,发送开始信号之后,一般需要调用simulate_i2c_write_byte()发送I2C子设备地址,然后才是调用simulate_i2c_write_byte()或simulate_i2c_read_byte()收发数据,每一个字节的数据后面都有一个ACK或NACK信号(发送地址时也有ack信号),根据情况调用simulate_i2c_send_ack(),simulate_i2c_send_no_ack()或者simulate_i2c_read_ack(),最后调用simulate_i2c_stop()发送停止信号,结束一次I2C通信过程。
为啥每个函数都有个相同的入参“simulate_i2c_t *i2c_info”呢?目的是告诉每个函数模拟I2C的GPIO引脚和I2C时钟周期,这样可以实现一个程序中同时支持多个不同的模拟I2C接口,接多个传感器。理论上GPIO越多,同时支持模拟I2C的个数就越多。
本文通过温湿度传感器AM2320来测试模拟的I2C接口,可以根据需要随意选取普通GPIO连接AM2320的SCL和SDA引脚。只是需要注意所选引脚是否接有其它元器件。
I2C接口是常用的接口之一,很多传感器都是使用I2C接口,本文使用普通GPIO模拟I2C,实现与温湿度传感器AM2320正常通信。 先展示如何使用模拟I2C接口,然后再来看看怎么封装这些接口的。
龙芯1c库中模拟I2C接口使用示例
模拟I2C接口简介
先来看看封装了那些接口,如下
// 模拟i2c的接口信息
typedef struct
{
unsigned int scl_gpio; // SCL所在gpio引脚
unsigned int sda_gpio; // SDA所在gpio引脚
int delay_time; // 周期的1/2,单位us
}simulate_i2c_t;
/*
* 模拟i2c初始化
* @i2c_info i2c的接口信息
*/
void simulate_i2c_init(simulate_i2c_t *i2c_info);
/*
* 模拟I2C的开始
* @i2c_info i2c接口信息
*/
void simulate_i2c_start(simulate_i2c_t *i2c_info);
/*
* 模拟I2C的停止
* @i2c_info i2c接口信息
*/
void simulate_i2c_stop(simulate_i2c_t *i2c_info);
/*
* 给从设备发送一个ack应答信号
* @i2c_info i2c接口信息
*/
void simulate_i2c_send_ack(simulate_i2c_t *i2c_info);
/*
* 给从设备发送一个no ack非应答信号
* @i2c_info i2c接口信息
*/
void simulate_i2c_send_no_ack(simulate_i2c_t *i2c_info);
/*
* 读取从设备的ack应答信号
* @i2c_info i2c接口信息
* @ret 读取到的信号。0表示应答,1表示非应答
*/
unsigned int simulate_i2c_read_ack(simulate_i2c_t *i2c_info);
/*
* 主设备从从设备那里读取一个8bit数据
* @i2c_info i2c接口信息
* @ret 读取的数据
*/
unsigned char simulate_i2c_read_byte(simulate_i2c_t *i2c_info);
/*
* 主设备写8bit数据到从设备
* @i2c_info i2c接口信息
* @data 待写数据
*/
void simulate_i2c_write_byte(simulate_i2c_t *i2c_info, unsigned char data);
系统初始化时,首先调用simulate_i2c_init()对gpio初始化,然后调用simulate_i2c_start()发送I2C的开始信号,发送开始信号之后,一般需要调用simulate_i2c_write_byte()发送I2C子设备地址,然后才是调用simulate_i2c_write_byte()或simulate_i2c_read_byte()收发数据,每一个字节的数据后面都有一个ACK或NACK信号(发送地址时也有ack信号),根据情况调用simulate_i2c_send_ack(),simulate_i2c_send_no_ack()或者simulate_i2c_read_ack(),最后调用simulate_i2c_stop()发送停止信号,结束一次I2C通信过程。
为啥每个函数都有个相同的入参“simulate_i2c_t *i2c_info”呢?目的是告诉每个函数模拟I2C的GPIO引脚和I2C时钟周期,这样可以实现一个程序中同时支持多个不同的模拟I2C接口,接多个传感器。理论上GPIO越多,同时支持模拟I2C的个数就越多。
本文通过温湿度传感器AM2320来测试模拟的I2C接口,可以根据需要随意选取普通GPIO连接AM2320的SCL和SDA引脚。只是需要注意所选引脚是否接有其它元器件。
用温湿度传感器AM2320测试模拟I2C接口
实物图
温湿度传感器AM2320占用的引脚
VDD ------------------ 3.3V
GND ------------------ GND
SCL ------------------ GPIO57
SDA ------------------ GPIO56
这里是用GPIO模拟的I2C,理论上所有GPIO都可以用作SCL和SDA。另外AM2320的芯片手册中推荐SCL和SDA接上拉电阻,实测不接也是可以的。
代码清单
main.c
#include "../lib/public.h"
#include "../lib/gpio.h"
#include "../lib/delay.h"
#include "../example/test_gpio.h"
#include "../example/test_pwm.h"
#include "../example/test_delay.h"
#include "../example/test_simulate_i2c.h"
// pmon提供的打印接口
struct callvectors *callvec;
int main(int argc, char **argv, char **env, struct callvectors *cv)
{
callvec = cv;
// -------------------------测试gpio----------------------
/*
* 测试库中gpio作为输出时的相关接口
* led闪烁10次
*/
// test_gpio_output();
/*
* 测试库中gpio作为输入时的相关接口
* 按键按下时,指示灯点亮,否则,熄灭
*/
// test_gpio_input();
// ------------------------测试PWM--------------------------------
// 测试硬件pwm产生连续的pwm波形
// test_pwm_normal();
// 测试硬件pwm产生pwm脉冲
// test_pwm_pulse();
/*
* 测试gpio04复用