本人使用Msp430G2553来实现软件模拟I2C,不过在参考网上的例程下改写I2C程序后,一直无法得到应答,有使用示波器检测过时序,是没有问题的,所以特向各位大牛求救哈,求大牛们帮帮忙。
我的I2C程序:
头文件:
/*
* I2C.h
*
* Created on: 2015-3-31
* Author: vecio
*/
#ifndef I2C_H_
#define I2C_H_
#define I2C_DIR P2DIR
#define I2C_OUT P2OUT
#define I2C_IN P2IN
#define I2C_SCL BIT1 //SCL P2.1 I2C的时钟模拟口
#define I2C_SDA BIT2 //SDA P2.2 I2C的数据模拟口
#define SDA_HIGH I2C_OUT |= I2C_SDA//SDA = 1
#define SDA_LOW I2C_OUT &= ~I2C_SDA//SDA = 0
#define SCL_HIGH I2C_OUT |= I2C_SCL//SCL = 1
#define SCL_LOW I2C_OUT &= ~I2C_SCL//SCL = 0
#define IIC_READ 0x0E //定义读指令
#define IIC_WRITE 0x0E //定义写指令
#define SET_SDA_IN I2C_DIR &= ~I2C_SDA //SET SDA IN
#define SET_SDA_OUT I2C_DIR |= I2C_SDA //SET SDA OUT
#define SDA_IN ( I2C_IN & I2C_SDA) //READ SDA DATA
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned long uint32;
typedef signed long int32;
typedef unsigned int uint;
extern void delay_5us() ;
extern void I2C_Write(uint8 uint8_Addr,uint8 R_Data);
extern char I2C_Read(uint8 uint8_Addr);
#endif /* I2C_H_ */
C语言文件:
/*
* I2C.c
*
* Created on: 2015-3-31
* Author: vecio
*/
#include <msp430.h>
#include "I2C.h"
//uint8 Ack_Sign;
/*******************************************************************************
* Function: delay_us
* Description: 延时1个机器周期
* Calls:
* Return: void
******************************************************************************/
void delay_us(void)
{
__no_operation();
}
/*******************************************************************************
* Function: delay_us
* Description: 延时2个机器周期
* Calls:
* Return: void
******************************************************************************/
void delay_2us(void)
{
__no_operation();
__no_operation();
}
/*******************************************************************************
* Function: delay_us
* Description: 延时5个机器周期
* Calls:
* Return: void
******************************************************************************/
void delay_5us(void)
{
__no_operation();
__no_operation();
__no_operation();
__no_operation();
__no_operation();
}
/*******************************************************************************
* Function: start
* Description: 起始位
* Calls:
* Return: void
******************************************************************************/
void I2C_Start()
{
SET_SDA_OUT;
SCL_HIGH; //拉高时钟线
delay_2us();
SDA_LOW; //拉低数据线
delay_2us();
SCL_LOW; //拉低时钟线
delay_2us();
}
/*******************************************************************************
* Function: stop
* Description: 停止位
* Calls:
* Return: void
******************************************************************************/
void I2C_Stop()
{
SET_SDA_OUT;
SCL_HIGH; //拉高时钟线
delay_5us();
SDA_LOW; //拉低数据线
delay_5us();
SDA_HIGH; //时钟线为高电平时,拉高数据线,产生停止信号
delay_5us();
}
/*******************************************************************************
* Function: ack
* Description: 应答标志
* Calls:
* Return: Ack_Sign
******************************************************************************/
uint8 I2C_Ack()
{
uint8 Ack_Sign;
SET_SDA_OUT;
SDA_HIGH; //释放数据总线,准备接收应答信号
delay_5us();
SCL_HIGH; //拉高时钟线
delay_5us();
Ack_Sign=SDA_IN; //读取应答信号的状态
delay_5us();
SCL_LOW; //拉低时钟线
delay_5us();
return Ack_Sign; //返回应答信号状态,0表示应答,1表示非应答
}
/*******************************************************************************
* Function: test_ack
* Description: 测试ACK
* Calls:
* Return: 1或者0
******************************************************************************/
uint8 TestAck()
{
uint8 Error_Bit;
SET_SDA_OUT;
SDA_HIGH;
delay_5us();
SCL_LOW;
delay_5us();
Error_Bit = SDA_IN;
SCL_LOW;
delay_5us();
if(Error_Bit == 0x00)
{
return 0;
}
else
return 1;
}
/*******************************************************************************
* Function: i2c_write_byte(uint8 wr)
* Description: 写入一个8bit数据
* Calls:
* Return: void
******************************************************************************/
void I2C_Write_byte(uint8 Wr)
{
uint8 c,Read_1,Read_2;
SET_SDA_OUT;
Read_1 = Wr;
for (c=0;c<8;c++)
{
SCL_LOW;
delay_5us();
Read_2 = Read_1;
Read_2 = Read_2&(0x80); //写最高位的数据
delay_5us();
if(Read_2 == (0x80) )
{
SDA_HIGH;
}
else
{
SDA_LOW;
}
delay_5us();
SCL_HIGH; //拉高时钟线,将数写入到设备中
delay_5us();
SCL_LOW; //拉低时钟线,允许改变数据线的状态
delay_5us();
Read_1 = Read_1 << 1 ; //数据左移一位,把次高位放在最高位,为写入次高位做准备
}
}
/*******************************************************************************
* Function: iic_read_byte()
* Description: 读出一个8bit数据
* Calls:
* Return: R_Data
******************************************************************************/
uint8 I2C_Read_byte()
{
uint8 L;
uint8 R_Data;
SET_SDA_IN;
SCL_LOW;
for(L=0;L<8;L++)
{
R_Data = R_Data << 1 ; //将缓冲字节的数据左移一位,准备读取数据
SDA_HIGH;
delay_5us();
SCL_LOW;
delay_5us();
SCL_HIGH;
delay_5us();
if(SDA_IN == 1)
{
R_Data = R_Data | (0x01) ; //如果数据线为高电平,则给缓冲字节的最低位写一
delay_5us();
}
}
return (R_Data); //返回读取的一个字节数据
}
/*******************************************************************************
* Function: iic_write(uint8 uint8_add,uint8 rdata)
* Description: 按任意地址写入一字节数据
* Calls:
* Return: void
******************************************************************************/
void I2C_Write(uint8 uint8_Addr,uint8 R_Data)
{
uint8 t;
t = (IIC_WRITE << 1 );
I2C_Start(); //产生起始信号
I2C_Write_byte(t); //写入设备地址(写)
I2C_Ack(); //等待设备应答
I2C_Write_byte(uint8_Addr); //写入要操作的单元地址
I2C_Ack(); //等待设备应答
I2C_Write_byte(R_Data); //写入数据
I2C_Ack(); //等待设备应答
I2C_Stop(); //产生停止信号
}
/*******************************************************************************
* Function: iic_read(uint8 uint8_add)
* Description: 按地址读出一字节数据
* Calls:
* Return: x
******************************************************************************/
char I2C_Read(uint8 uint8_Addr)
{
uint8 t,x;
t=(IIC_READ << 1 ) ;
I2C_Start(); //产生起始信号
I2C_Write_byte(t); //写入设备地址(写)
I2C_Ack(); //等待设备的应答
I2C_Write_byte(uint8_Addr) ; //写入要操作的单元地址
I2C_Ack(); //等待设备应答
t=((IIC_READ << 1) | 0x01) ;
I2C_Start(); //产生起始信号
I2C_Write_byte(t); //写入设备地址(读)
I2C_Ack(); //等待设备的应答
x = I2C_Read_byte(); //写入数据
I2C_Ack(); //等待设备的应答
I2C_Stop(); //产生停止信号
return x; //返回读取的一个字节数据
}
求大家帮帮忙哈
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
{
uint8 Ack_Sign;
SET_SDA_OUT;
SDA_HIGH; //释放数据总线,准备接收应答信号
delay_5us();
SCL_HIGH; //拉高时钟线
delay_5us();
Ack_Sign=SDA_IN; //读取应答信号的状态
delay_5us();
SCL_LOW; //拉低时钟线
delay_5us();
return Ack_Sign; //返回应答信号状态,0表示应答,1表示非应答
}
上面的SDA没有设置成输入
,
一周热门 更多>