CC2541 硬件I2C读取寄存器返回值错误

CC2541 硬件I2C读取寄存器返回值错误

做的项目需要用到CC2541的硬件I2C功能,使用的是TI的I2C驱动。但是调试时读取不同寄存器的数据全都一样,用示波器监控信号时发现:
读取寄存器地址时发送的从机地址寄存器地址都正确,而且从机也应答了并且返回从机地址+数据,当读取不同寄存器数据时返回的却都是从机地址+固定的一串数据。。猜测硬件的I2C可能读取数据时错误

所以试了下用SDA、SCL的引脚做模拟I2C的功能,能正常返回读取各寄存器的数据

直接用SDA、SCL引脚做模拟I2C功能代码
.c文件


#include "sw_i2c.h"

/**
 *  初始化I2C数据引脚
 */
void SW_I2C_Init(void)
{
    I2C_GPIO;
    SDA_OUT;	
    SCL_OUT;
	SDA_1;  //SDA = 1;
	SCL_1;  //SCL = 1;
}

/********************************************
* 名称:i2c_send_noack()              												
* 功能:无应答I2C总线                  											
* 参数:无                             											
* 返回:1 有NOACK信号 0 无NOACK信号                             					
 */
void send_noack(){
	SDA_OUT;	 
	SDA_1;  //SDA = 1; NO ACK
	DELAY_I2C;
	SCL_1;  //SCL = 1;
	DELAY_I2C;
	SCL_0;  //SCL = 0;	//START
	DELAY_I2C;
}
// iic 应答  for slaver
void send_ack() {
	SDA_OUT;	
	SDA_0; //OUT 0 ACK
	DELAY_I2C;
	SCL_1;
	DELAY_I2C;
	SCL_0;
	DELAY_I2C;
}


/*
 * 起始位
 */
static void start(){
	SDA_OUT;	
    SCL_OUT;
	SDA_1;  //SDA = 1;
	DELAY_I2C;
	SCL_1;  //SCL = 1;
	DELAY_I2C;
	SDA_0;  //SDA = 0;
}

/*
 *停止位
 */
static void stop(){
	SDA_OUT;	
    SCL_OUT;
	SDA_0;  //SDA = 0;
	DELAY_I2C;
	SCL_1;  //SCL = 1;	STOP
	DELAY_I2C;
	SDA_1;  //SDA = 1;
}



/**
 * 向从机写一个字节
 */
void iic_write_byte(uint8 datIn) {
	uint8 data, j;
	data = datIn;
        SDA_OUT;
	for (j = 0; j < 8; j++) {
        SCL_0;
        DELAY_I2C;

        if((data & 0x80)) SDA_1;
        else SDA_0;

		SCL_1;	//write TDOS_SDA begin
        DELAY_I2C;

		data <<= 1;
	}
    SCL_0;
	DELAY_I2C;
}

bool check_ack() {
	bool ack_flag;

	SDA_IN;	//开路输入,
	SCL_1;	//read ask begin
	DELAY_I2C;
	
        if((I2CIO & I2C_SDAD) ==1){ //if (SDA==1)
		ack_flag = 0; //1: err
	}else{
		ack_flag = 1; //0: ok
	}
	SCL_0;	//read ask end
	return ack_flag;
}

/*
 * 读一个字节
 */
uint8 iic_read() {
	uint8 j, data = 0;
    SCL_OUT;
	SDA_IN;	//输入
    DELAY_I2C; 
    
	for (j = 0; j < 8; j++) {
		SCL_1;	//read TDOS_SDA begin. delay 0.7us
        DELAY_I2C; 
		data <<= 1;
            if((I2CIO & I2C_SDAD) ==1){ //if (SDA==1)
            data |= 0x01; //input TDOS_SDA
            }
		SCL_0;	//read TDOS_SDA end. delay 1.4us
        DELAY_I2C; 
	}
	return data;
}
/*
 * 通过I2C总线向某一寄存器写入一个字节数据
 */
void I2C_write_byte(uint8 I2C_addr, uint8 reg, uint8 data)
{
	start(); //发启动信号
	iic_write_byte((I2C_addr << 1) | 0x00); //从机地址
	if (check_ack()==0) {
		goto err;
	}
	iic_write_byte(reg); //发送寄存器地址
	if (check_ack()==0) {
		goto err;
	}
	iic_write_byte(data); //发送数据字节
	if (check_ack()==0) {
		goto err;
	}
err:
	stop();
}

/*
 * 通过I2C总线读出某一寄存器的数据
 */
uint8 I2C_read_byte(uint8 I2C_addr, uint8 reg) 
{
	uint8 data;

	start();
	iic_write_byte((I2C_addr << 1) | 0X00); //WRITE i2c
	if (check_ack()==0) {
		goto err;
	}
	iic_write_byte(reg); //TDOS'register
	if (check_ack()==0) {
		goto err;
	}
	start(); //重发起动信号
	iic_write_byte((I2C_addr << 1) | 0X01); //READ
	if (check_ack()==0) {
		goto err;
	}
	data = iic_read();	//接收读出的数据
	send_noack();
err:
	stop();
	return data;
}
/*
 * 通过I2C总线读出某一寄存器的数据
 */
uint16 I2C_read_2byte(uint8 I2C_addr, uint8 reg) 
{
	uint8 data1,data2;

	start();
	iic_write_byte((I2C_addr << 1) | 0X00); //WRITE i2c
	if (check_ack()==0) {
		goto err;
	}
	iic_write_byte(reg); //TDOS'register
	if (check_ack()==0) {
		goto err;
	}
	start(); //重发起动信号
	iic_write_byte((I2C_addr << 1) | 0X01); //READ
	if (check_ack()==0) {
		goto err;
	}
	data1 = iic_read();	//接收读出的数据
 	send_ack();
	data2 = iic_read();	//接收读出的数据

	send_noack();
err:
	stop();
	return data1 | (data2 << 8) ;
}

头文件.h

#ifndef _SW_IIC_H_
#define _SW_IIC_H_

#include <ioCC2541.h>
#include "hal_types.h"
#include "hal_defs.h"


/* Ative delay: 125 cycles ~1 msec */
#define ST_HAL_DELAY(n) st( { volatile uint32 i; for (i=0; i<(n); i++) { }; } )
#define DELAY_I2C   ST_HAL_DELAY(1) //125KHz~8us
/* ------------------------------------------------------------------------------------------------
 *                                          Constants
 * ------------------------------------------------------------------------------------------------
 */
// I2CWC
#define I2C_OVR            BV(7) // 1: GPIO functionality.0: I2C functionality
#define I2C_SCLPUE         BV(3) //SCL pin pullup enable
#define I2C_SDAPUE         BV(2) //SDA pin pullup enable.
#define I2C_SCLOE          BV(1) //SCL pin output enable
#define I2C_SDAOE          BV(0) //SDA pin output enable

// I2CIO
#define I2C_SCLD             BV(1) //SCL data value
#define I2C_SDAD             BV(0) //SDA data value

#define SDA_0      I2CIO &= ~I2C_SDAD //SDA=0
#define SDA_1      I2CIO |= I2C_SDAD  //SDA=1
#define SCL_0      I2CIO &= ~I2C_SCLD //SCL=0
#define SCL_1      I2CIO |= I2C_SCLD  //SCL=1

#define SDA_IN      I2CWC &= ~I2C_SDAOE //SDA INPUT
#define SDA_OUT     I2CWC |= I2C_SDAOE  //SDA OUTPUT
#define SCL_IN      I2CWC &= ~I2C_SCLOE //SCL INPUT
#define SCL_OUT     I2CWC |= I2C_SCLOE  //SCL OUTPUT

#define I2C_GPIO    st(I2CWC = 0x80;) //1: I2C GPIO


/**
 * 软件I2C初始化
 */
void SW_I2C_Init(void);

/**
 * 写一个字节的数据
 * @param   
 *          I2C_addr 从机地址
            Raddr    寄存器地址
            dat      8bit数据
 */
void I2C_write_byte(uint8 I2C_addr, uint8 reg, uint8 dat);

/**
 * 读寄存器数据,16bit
 * @param   
 *          I2C_addr 从机地址
            Raddr    寄存器地址
 * @return  16bit数据
 */
uint16 I2C_read_2byte(uint8 I2C_addr, uint8 reg) ;

#endif
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是读取 I2C 从机寄存器的代码示例: ``` uint8_t read_from_i2c(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, uint8_t len) { uint8_t result; uint8_t tx_data[1] = {reg_addr}; i2c_master_transfer_t masterXfer; /* 初始化 I2C 主机 */ I2C_MasterTransferCreateHandle(I2C0, &g_master_handle, i2c_master_callback, NULL); /* 设置从机地址 */ masterXfer.slaveAddress = slave_addr; masterXfer.direction = kI2C_Write; masterXfer.subaddress = 0; masterXfer.subaddressSize = 0; masterXfer.data = tx_data; masterXfer.dataSize = 1; masterXfer.flags = kI2C_TransferDefaultFlag; /* 发送从机寄存器地址 */ result = I2C_MasterTransferBlocking(I2C0, &g_master_handle, &masterXfer); if (result != kStatus_Success) { return result; } /* 设置从机地址 */ masterXfer.slaveAddress = slave_addr; masterXfer.direction = kI2C_Read; masterXfer.subaddress = 0; masterXfer.subaddressSize = 0; masterXfer.data = data; masterXfer.dataSize = len; masterXfer.flags = kI2C_TransferDefaultFlag; /* 读取从机寄存器数据 */ result = I2C_MasterTransferBlocking(I2C0, &g_master_handle, &masterXfer); if (result != kStatus_Success) { return result; } return kStatus_Success; } ``` 上述代码中,使用了 KSDK (Keil Software Development Kit) 提供的 I2C 库函数,其中 `I2C0` 是 I2C 模块的实例,`slave_addr` 是从机地址,`reg_addr` 是从机寄存器地址,`data` 是读取的数据,`len` 是读取数据的长度。函数首先发送从机寄存器地址,然后再读取从机寄存器中的数据。函数返回值是操作的状态,可以根据返回值判断操作是否成功。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值