Kendryte K210 使用GPIO模拟i2c波形

K210自带的i2c有个不好的地方,就是当你读取数据的时候,若因为地址问题没有通讯上的话,是没有办法通过示波器来测试这个设备是否应答的,只发一次若不应答就会把程序给卡死,所以有些时候还是需要用到模拟的i2c来测试,但模拟的i2c也有一个不好的地方就是速率比较慢,若是一些寄存器相对较少的可以,但多起来了不排除有错误的风险。

整理一下相关代码,如下,这里随便找了一个设备来做这个例子代码,大同小异,根据需求来改即可,代码写得不够精简,请见谅:

#ifndef _I2C_GM7122_H
#define _I2C_GM7122_H

#include 
#include 
#include 
#include 
#include 

#define GM7122_SLAVE_ADDRESS   0x44


void GM7122_i2c_master_init(void);
uint8_t GM7122_i2c_write_reg(uint8_t reg, uint8_t *data_buf, size_t length);
uint8_t GM7122_i2c_read_reg(uint8_t reg, uint8_t *data_buf, size_t length);
uint8_t GM7122_init(void);
#endif
#include 
#include 
#include "i2c_GM7122.h"

#define DELAY_TIME  10
static handle_t piohs;
static handle_t pwm1;
#define GM7122_SCL 8
#define GM7122_SDA 9

void GM7122_i2c_master_init(void)
{
    piohs = io_open("/dev/gpio0");
    gpio_set_drive_mode(piohs, GM7122_SCL, GPIO_DM_OUTPUT);
    gpio_set_drive_mode(piohs, GM7122_SDA, GPIO_DM_OUTPUT);
    gpio_set_drive_mode(piohs, 10, GPIO_DM_OUTPUT);
    gpio_set_pin_value(piohs, GM7122_SCL, GPIO_PV_HIGH);
    gpio_set_pin_value(piohs, GM7122_SDA, GPIO_PV_HIGH);
    gpio_set_pin_value(piohs, 10, GPIO_PV_HIGH);
}

void GM7122_i2c_start(void)
{
    gpio_set_drive_mode(piohs, GM7122_SDA, GPIO_DM_OUTPUT);
    gpio_set_pin_value(piohs, GM7122_SDA, GPIO_PV_HIGH);
    gpio_set_pin_value(piohs, GM7122_SCL, GPIO_PV_HIGH);
    usleep(DELAY_TIME);
    gpio_set_pin_value(piohs, GM7122_SDA, GPIO_PV_LOW);
    usleep(DELAY_TIME);
    gpio_set_pin_value(piohs, GM7122_SCL, GPIO_PV_LOW);
}

void GM7122_i2c_stop(void)
{
    gpio_set_drive_mode(piohs, GM7122_SDA, GPIO_DM_OUTPUT);
    gpio_set_pin_value(piohs, GM7122_SDA, GPIO_PV_LOW);
    gpio_set_pin_value(piohs, GM7122_SCL, GPIO_PV_HIGH);
    usleep(DELAY_TIME);
    gpio_set_pin_value(piohs, GM7122_SDA, GPIO_PV_HIGH);
}

uint8_t GM7122_i2c_send_byte(uint8_t data)
{
    uint8_t index;

    gpio_set_drive_mode(piohs, GM7122_SDA, GPIO_DM_OUTPUT);
    for (index = 0; index < 8; index++)
    {
        if (data & 0x80)
            gpio_set_pin_value(piohs, GM7122_SDA, GPIO_PV_HIGH);
        else
            gpio_set_pin_value(piohs, GM7122_SDA, GPIO_PV_LOW);
        usleep(DELAY_TIME);
        gpio_set_pin_value(piohs, GM7122_SCL, GPIO_PV_HIGH);
        usleep(DELAY_TIME);
        gpio_set_pin_value(piohs, GM7122_SCL, GPIO_PV_LOW);
        data <<= 1;
    }
    gpio_set_drive_mode(piohs, GM7122_SDA, GPIO_DM_INPUT);
    usleep(DELAY_TIME);
    gpio_set_pin_value(piohs, GM7122_SCL, GPIO_PV_HIGH);
    data = gpio_get_pin_value(piohs, GM7122_SDA);
    usleep(DELAY_TIME);
    gpio_set_pin_value(piohs, GM7122_SCL, GPIO_PV_LOW);

    return data;
}

uint8_t GM7122_i2c_receive_byte(uint8_t ack)
{
    uint8_t index, data = 0;

    gpio_set_drive_mode(piohs, GM7122_SDA, GPIO_DM_INPUT);
    for (index = 0; index < 8; index++)
    {
        usleep(DELAY_TIME);
        gpio_set_pin_value(piohs, GM7122_SCL, GPIO_PV_HIGH);
        data <<= 1;
        if (gpio_get_pin_value(piohs, GM7122_SDA))
            data++;
        usleep(DELAY_TIME);
        gpio_set_pin_value(piohs, GM7122_SCL, GPIO_PV_LOW);
    }
    gpio_set_drive_mode(piohs, GM7122_SDA, GPIO_DM_OUTPUT);
    if (ack)
        gpio_set_pin_value(piohs, GM7122_SDA, GPIO_PV_HIGH);
    else
        gpio_set_pin_value(piohs, GM7122_SDA, GPIO_PV_LOW);
    usleep(DELAY_TIME);
    gpio_set_pin_value(piohs, GM7122_SCL, GPIO_PV_HIGH);
    usleep(DELAY_TIME);
    gpio_set_pin_value(piohs, GM7122_SCL, GPIO_PV_LOW);

    return data;
}

uint8_t GM7122_i2c_write_reg(uint8_t reg, uint8_t *data_buf, size_t length)
{
    GM7122_i2c_start();
    GM7122_i2c_send_byte(GM7122_SLAVE_ADDRESS << 1);
    GM7122_i2c_send_byte(reg);
    while (length--)
        GM7122_i2c_send_byte(*data_buf++);
    GM7122_i2c_stop();

    return 0;
}

uint8_t GM7122_i2c_read_reg(uint8_t reg, uint8_t *data_buf, size_t length)
{
    GM7122_i2c_start();
    GM7122_i2c_send_byte(GM7122_SLAVE_ADDRESS << 1);
    GM7122_i2c_send_byte(reg);
    GM7122_i2c_start();
    GM7122_i2c_send_byte((GM7122_SLAVE_ADDRESS << 1) + 1);
    while (length > 1L)
    {
        *data_buf++ = GM7122_i2c_receive_byte(0);
        length--;
    }
    *data_buf++ = GM7122_i2c_receive_byte(1);
    GM7122_i2c_stop();

    return 0;
}

uint8_t GM7122_init(void)
{
    uint8_t GM7122_init_reg[17] = {0x28, 0x29, 0x3A, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x6B, 0x6C, 0x6D};
    uint8_t GM7122_init_buf[17] = {0x21, 0x1D, 0x03, 0x00, 0x6D, 0x9F, 0x0E, 0x1C, 0x06, 0x3B, 0xCB, 0x8A, 0x09, 0x2A, 0x00, 0x51, 0x11};
    uint8_t temp[17] ;
    uint8_t i;


    printf("GM7122 i2c init start\r\n");
    GM7122_i2c_master_init();

    for(i=0 ; i<17 ; i++){
        GM7122_i2c_write_reg(GM7122_init_reg[i],&GM7122_init_buf[i],1);
        GM7122_i2c_read_reg(GM7122_init_reg[i] ,&temp[i],1);
        printf("[GM7122]0x%x -> 0x%x\r\n",GM7122_init_reg[i],temp[i]);
    }
    printf("GM7122 i2c init is ok\r\n");
    return 0;
}

 

你可能感兴趣的:(Kendryte,K210)