基于stm32f1的开发板,模拟的I2C通信程序 哪里错了啊 返回...
#include "stm32f10x.h"
#include "I2C.h"
#include <stdio.h>
/* Private typedef -----------------------------------------------------------*/
#define Device_Addr 0xe8
/* Private define ------------------------------------------------------------*/
/* I2C控制线的定义 */
#define SCL_H GPIOB->BSRR = GPIO_Pin_9
#define SCL_L GPIOB->BRR = GPIO_Pin_9
#define SDA_H GPIOB->BSRR = GPIO_Pin_8
#define SDA_L GPIOB->BRR = GPIO_Pin_8
#define SCL_read GPIOB->IDR & GPIO_Pin_9
#define SDA_read GPIOB->IDR & GPIO_Pin_8
void I2C_GPIO_Config(void);
void I2C_delay(void);
bool I2C_Start(void);
void I2C_Stop(void);
void I2C_Ack(void);
void I2C_NoAck(void);
bool I2C_WaitAck(void);
void I2C_SendByte(u8 SendByte);
void I2C_FM_Init(void);
void I2C_Write(u8 address,u8 reg,u8 command);
//bool I2C_Write(uint8_t* pBuffer, uint8_t Write, uint8_t NumByteToWrite);
extern void Delay(__IO uint32_t nCount);
void FM_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
/* 配置PB10,PB11为I2C的 SCL SDL */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9| GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void I2C_FM_Init(void)
{
/* I2C控制线配置 */
FM_Configuration();
/* I2C 初始化 */
//I2C_Configuration();
}
//模拟I2C信号
void I2C_INIT(void) //i2c init
{
SDA_H;
SCL_H;
}
void I2C_Write(u8 address,u8 reg,u8 command) //address+register+command
{
I2C_INIT();
I2C_Start();
I2C_SendByte(address);
I2C_Ack();
I2C_SendByte(reg);
I2C_Ack();
I2C_SendByte(command);
I2C_Ack();
I2C_Stop();
}
/****************************************************************************
* 名 称:void I2C_delay(void)
* 功 能:I2C 控制延时函数
* 入口参数:无
* 出口参数:无
* 说 明:无
* 调用方法:无
****************************************************************************/
void I2C_delay(void)
{
u8 i=100;
while(i)
{
i--;
}
}
/****************************************************************************
* 名 称:bool I2C_Start(void)
* 功 能:I2C起始状态
* 入口参数:无
* 出口参数:无
* 说 明:无
* 调用方法:无
****************************************************************************/
bool I2C_Start(void)
{
SDA_H; //SDA置高
SCL_H; //SCL置高
I2C_delay();
if(!SDA_read)return FALSE; //SDA线为低电平则总线忙,退出
SDA_L;
I2C_delay();
if(SDA_read) return FALSE; //SDA线为高电平则总线出错,退出
SDA_L; //SDA置低
I2C_delay();
return TRUE;
}
/****************************************************************************
* 名 称:void I2C_Stop(void)
* 功 能:I2C停止状态
* 入口参数:无
* 出口参数:无
* 说 明:无
* 调用方法:无
****************************************************************************/
void I2C_Stop(void)
{
SCL_L;
I2C_delay();
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SDA_H;
I2C_delay();
}
/****************************************************************************
* 名 称:void I2C_Ack(void)
* 功 能:I2C ACK应答
* 入口参数:无
* 出口参数:无
* 说 明:无
* 调用方法:无
****************************************************************************/
void I2C_Ack(void)
{
SCL_L;
I2C_delay();
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
I2C_delay();
}
/****************************************************************************
* 名 称:void I2C_NoAck(void)
* 功 能:I2C 无应答
* 入口参数:无
* 出口参数:无
* 说 明:无
* 调用方法:无
****************************************************************************/
void I2C_NoAck(void)
{
SCL_L;
I2C_delay();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
I2C_delay();
}
/****************************************************************************
* 名 称:bool I2C_WaitAck(void)
* 功 能:I2C等待应答
* 入口参数:无
* 出口参数:无
* 说 明:无
* 调用方法:无
****************************************************************************/
bool I2C_WaitAck(void) //返回为:=1有ACK,=0无ACK
{
SCL_L;
I2C_delay();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
if(SDA_read)
{
SCL_L;
return FALSE;
}
SCL_L;
return TRUE;
}
/****************************************************************************
* 名 称:void I2C_SendByte(u8 SendByte)
* 功 能:发送数据字节
* 入口参数:无
* 出口参数:无
* 说 明:无
* 调用方法:无
****************************************************************************/
void I2C_SendByte(u8 SendByte) //数据从高位到低位//
{
u8 i=8;
while(i--)
{
SCL_L;
I2C_delay();
if(SendByte&0x80)
SDA_H;
else
SDA_L;
SendByte<<=1;
I2C_delay();
SCL_H;
I2C_delay();
}
SCL_L;
}
/****************************************************************************
* 名 称:u8 I2C_ReceiveByte(void)
* 功 能:I2C接收数据字节
* 入口参数:无
* 出口参数:无
* 说 明:无
* 调用方法:无
****************************************************************************/
u8 I2C_ReceiveByte(void) //数据从高位到低位//
{
u8 i=8;
u8 ReceiveByte=0;
SDA_H;
while(i--)
{
ReceiveByte<<=1;
SCL_L;
I2C_delay();
SCL_H;
I2C_delay();
if(SDA_read)
{
ReceiveByte|=0x01;
}
}
SCL_L;
return ReceiveByte;
}
u8 read_byte(u8 address,u8 reg) //address(with bit 0 set) + register
{
u8 dat;
I2C_INIT();
I2C_Start();
I2C_SendByte(address);
I2C_Ack();
I2C_SendByte(reg);
I2C_Ack();
I2C_Start();
I2C_SendByte(address+1);
I2C_Ack();
dat = I2C_ReceiveByte();
I2C_NoAck();
I2C_Stop();
return dat;
}
//
//void change_i2c_address(unsigned char addr_old, unsigned char addr_new)
//// addr_old is the address now, addr_new will be the new address
//{ //that you want change to
//delayms(2000);
//I2C_Write(&write_command, WriteAddr, 3) // Protect the eeprom ,you can delete this sentence
//write_byte(addr_old,2,0x9a);
//delayms(1);
//write_byte(addr_old,2,0x92);
//delayms(1);
//write_byte(addr_old,2,0x9e);
//delayms(1);
//write_byte(addr_old,2, addr_new);
//delayms(500); //Protect the eeprom, you can delete this sentence
//}
static void Delay_ARMJISHU(__IO uint32_t nCount)
{
for (; nCount != 0; nCount--);
}
void detect(void) //0xe8(address) + 0xb0(command)
{
u8 i;
// u8 I2c_voice[3]={0xe8,2,0xb0};
u8 I2c_Buf[2];
I2C_Write(Device_Addr,2,0xb4);
// I2C_Write(I2c_voice, Device_Addr,3); //use command "0xb0" to detect the distance
Delay_ARMJISHU(360000); //安全延时,如果显示不清晰可以将延时调大一些
//delayms(80); //如果是探测温度此处延时需根据表1所列时间相应延长
//display(range); //等待探测结束,count值调小将减小探测等待时间
while(!GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9));//display(range);
I2c_Buf[0]=read_byte(Device_Addr,2);
I2c_Buf[1]=read_byte(Device_Addr,3);
for(i=0;i<=2;i++)
{
printf("0x%X\t", I2c_Buf);
}
}