269837846 发表于 2014-5-9 10:30:07

stm32 24c02 接收数据0xff

本帖最后由 269837846 于 2014-5-9 11:25 编辑

好心人帮忙程序如下:


/*******************************************************************************
* 文件名            : main.c
* 作者                 : Losingamong
* 生成日期        : 14/09/2010
* 描述                           : 主程序
*******************************************************************************/


/* 头文件 ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"
#include "stdio.h"

/* 自定义同义关键字    -------------------------------------------------------*/

/* 自定义参数宏      -------------------------------------------------------*/

void delay(unsigned int t)
{//延时函数
    while(t){t--;};                  //延时循环计数
}
void delay_IIC(void)   
{u8 i=80; //这里可以优化速度 ,经测试最低到5还能写入
   while(i)
   {
   i--;
   }
}


#define PB7_OUT() {GPIOB->CRL&=0x0fffffff;GPIOB->CRL|=0x30000000;        }
#define PB7_IN() {GPIOB->CRL&=0x0fffffff;GPIOB->CRL|=0x80000000;        }
#define SDA1() {GPIO_SetBits(GPIOB, GPIO_Pin_7);}
#define SDA0() {GPIO_ResetBits(GPIOB, GPIO_Pin_7);}
#define SCL1() {GPIO_SetBits(GPIOB, GPIO_Pin_6);}
#define SCL0() {GPIO_ResetBits(GPIOB, GPIO_Pin_6);}

//-------------------------------------------------------------------
void IIC_Init(void)
{//IIC总线初始化函数
    SDA1();//释放IIC总线的数据线。
    SCL0();//释放IIC总线的时钟线。
}

//-------------------------------------------------------------------
void IIC_start(void)
{//IIC总线产生起始信号函数
    SDA1();//拉高数据线
    SCL1();//拉高时钟线
    delay_IIC();
    SDA0();//在时钟线为高电平时,拉低数据线,产生起始信号。
    delay_IIC();
    SCL0();//拉低时钟线
}


//-------------------------------------------------------------------
void IIC_stop(void)
{//IIC总线产生停止信号函数
    SDA0();//拉低数据线
    delay_IIC();
    SCL1();//拉高时钟线。
    delay_IIC();
    SDA1();//时钟时线为高电平时,拉高数据线,产生停止信号。
    delay_IIC();
}

//-------------------------------------------------------------------
u8 IIC_Tack(void)
{//接收应答信号函数
    u8 ack;//定义一个位变量,来暂存应答状态。
    SDA1();//释放数据总线,准备接收应答信号。
    delay_IIC();
    SCL1();//拉高时钟线。
    delay_IIC();
        PB7_IN();
    ack= GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_7);//读取应答信号的状态。
        PB7_OUT();
    delay_IIC();
    SCL0();//拉低时钟线。
    delay_IIC();
    return ack;//返回应答信号的状态,0表示应答,1表示非应答。
}

//-------------------------------------------------------------------
void IIC_write_byte(u8 Data)
{//向IIC总线写入一个字节的数据函数
    u8 i;
   for(i=0;i<8;i++)//有8位数据
    {
      if(Data&0x80)//写最高位的数据
             {SDA1();}
          else
               {SDA0();}
       delay_IIC();
       SCL1(); //拉高时钟线,将数写入到设备中。
       delay_IIC();
           delay_IIC();
       SCL0();//拉低时钟线,允许改变数据线的状态
       delay_IIC();
           delay_IIC();
       Data=Data<<1;//数据左移一位,把次高位放在最高位,为写入次高位做准备
    }
}

//-------------------------------------------------------------------
unsigned char IIC_read_byte()
{//从IIC总线读取一个字节的数据函数
    u8 i;
    u8 Data;       //定义一个缓冲寄存器。
        PB7_IN();
    for(i=0;i<8;i++)//有8位数据
    {
      SCL1();//拉高时钟线,为读取下一位数据做准备。
      delay_IIC();
      Data=Data<<1;//将缓冲字节的数据左移一位,准备读取数据。
      delay_IIC();
      
      if(GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_7))//如果数据线为高平电平。
            Data=Data|0x1;//则给缓冲字节的最低位写1。
      SCL0();//拉低时钟线,为读取下一位数据做准备。
      delay_IIC();
    }
        PB7_OUT();
    return Data;//返回读取的一个字节数据。
}
//-------------------------------------------------------------------
void IIC_single_byte_write(u8 Daddr,u8 Waddr,u8 Data)
{//向任意地址写入一个字节数据函数
    IIC_start();//产生起始信号
    IIC_write_byte(Daddr);//写入设备地址(写)
    IIC_Tack();//等待设备的应答
    IIC_write_byte(Waddr);//写入要操作的单元地址。
    IIC_Tack();//等待设备的应答。
    IIC_write_byte(Data);//写入数据。
    IIC_Tack();//等待设备的应答。
    IIC_stop();//产生停止符号。
}

//-------------------------------------------------------------------
u8 IIC_single_byte_read(u8 Daddr,u8 Waddr)
{//从任意地址读取一个字节数据函数
    unsigned char Data;//定义一个缓冲寄存器。

    IIC_start();//产生起始信号
    IIC_write_byte(Daddr);//写入设备地址(写)
    IIC_Tack();//等待设备的应答
    IIC_write_byte(Waddr);//写入要操作的单元地址。
    IIC_Tack();//等待设备的应答。
   
    IIC_start();//产生起始信号
    IIC_write_byte(Daddr+1);//写入设备地址(读)。
    IIC_Tack();//等待设备的应答。
    Data=IIC_read_byte();//写入数据。
    IIC_stop();//产生停止符号。
    //-------------------返回读取的数据--------------------
    return Data;//返回读取的一个字节数据。
}



/* 自定义函数宏      -------------------------------------------------------*/

/* 自定义变量          -------------------------------------------------------*/

/* 用户函数声明 ---------------------------------------------------------*/

void RCC_Configuration(void);
void GPIO_Configuration(void);

void USART_Configuration(void);



int main(void)
{
   
        /* 设置系统时钟 */
        RCC_Configuration();
        /* 设置GPIO端口 */
        GPIO_Configuration();
        /* 设置USART */
        USART_Configuration();
        while(1)
        {
        u8 iic_data=0x00;
        printf("\r\n The I2C is ready!!!\n");
                       
        IIC_single_byte_write(0xA0,0x01,0x66);
        printf("\r\n The I2C write!!!\n");
        iic_data=IIC_single_byte_read(0xA0,0x01);
        printf("\r\n The I2C1 has read data 0x%x\r\n", iic_data);
        iic_data=IIC_single_byte_read(0xA0,0x02);
        printf("\r\n The I2C1 has read data 0x%x\r\n", iic_data);
        }
}


void RCC_Configuration(void)
{
        ErrorStatus HSEStartUpStatus;
       
        RCC_DeInit();
        RCC_HSEConfig(RCC_HSE_ON);
        HSEStartUpStatus = RCC_WaitForHSEStartUp();
        if(HSEStartUpStatus == SUCCESS)
        {
                FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
                FLASH_SetLatency(FLASH_Latency_2);
                RCC_HCLKConfig(RCC_SYSCLK_Div1);
                RCC_PCLK2Config(RCC_HCLK_Div1);
                RCC_PCLK1Config(RCC_HCLK_Div2);
                RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);       
                RCC_PLLCmd(ENABLE);
                while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
                RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
                while(RCC_GetSYSCLKSource() != 0x08);
        }
       
        /* 开启 I2C1、I2C2 设备时钟 */
        //RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 | RCC_APB1Periph_I2C2, ENABLE);
        /* 开启 GPIOA、GPIOB和 USART 设备时钟 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
}


void GPIO_Configuration(void)
{
        /* 定义 GPIO 初始化结构体 GPIO_InitStructure */
        GPIO_InitTypeDef GPIO_InitStructure;
       
        /* 配置 I2C1 设备的引脚为复用开漏模式 */
        GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6 | GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
       
        /* 配置 I2C2 设备的引脚为复用开漏模式
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
        GPIO_Init(GPIOB, &GPIO_InitStructure); */
       
        /* 配置 USART 设备引脚 */       
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}







void USART_Configuration(void)
{
    /* 定义USART初始化结构体 USART_InitStructure */
    USART_InitTypeDef USART_InitStructure;
    /* 定义USART初始化结构体 USART_ClockInitStructure */
    USART_ClockInitTypeDefUSART_ClockInitStructure;
   
    /*       
        *        波特率为115200bps;
    *        8位数据长度;
    *        1个停止位,无校验;
    *        禁用硬件流控制;
    *        禁止USART时钟;
    *        时钟极性低;
    *        在第2个边沿捕获数据
    *        最后一位数据的时钟脉冲不从 SCLK 输出;
    */
    USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
    USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
    USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
    USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
    USART_ClockInit(USART1 , &USART_ClockInitStructure);
   
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No ;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1 , &USART_InitStructure);
   
    /* 使能USART1 */
    USART_Cmd(USART1 , ENABLE);
}

#pragma import(__use_no_semihosting)
_sys_exit(int x)
{
x = x;
}
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
/* FILE is typedef’ d in stdio.h. */
FILE __stdout;
int fputc(int ch, FILE *f)
{
    USART_SendData(USART1, (u8) ch);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
    return ch;
}

269837846 发表于 2014-5-9 10:31:12

貌似是写不进24c02

269837846 发表于 2014-5-9 10:32:18

坐等回复

machao 发表于 2014-5-15 09:50:31

坐等天上掉馅饼

男小北 发表于 2014-5-17 10:12:12

马老师都开口了;楼主还是自己慢慢调吧

xiaoyigechaos 发表于 2014-5-17 11:44:13

void IIC_single_byte_write(u8 Daddr,u8 Waddr,u8 Data)
{//向任意地址写入一个字节数据函数
    IIC_start();//产生起始信号
    IIC_write_byte(Daddr);//写入设备地址(写)
    IIC_Tack();//等待设备的应答
    IIC_write_byte(Waddr);//写入要操作的单元地址。
    IIC_Tack();//等待设备的应答。
    IIC_write_byte(Data);//写入数据。
    IIC_Tack();//等待设备的应答。
    IIC_stop();//产生停止符号。
}

写数据时序?对吗

269837846 发表于 2014-5-22 21:12:07

machao 发表于 2014-5-15 09:50
坐等天上掉馅饼

走投无路了,才来请教大家的,不好意思{:loveliness:}

269837846 发表于 2014-5-22 21:13:17

xiaoyigechaos 发表于 2014-5-17 11:44
void IIC_single_byte_write(u8 Daddr,u8 Waddr,u8 Data)
{//向任意地址写入一个字节数据函数
    IIC_star ...

是波特率没有设置好,谢谢啊

269837846 发表于 2014-5-22 21:13:57

男小北 发表于 2014-5-17 10:12
马老师都开口了;楼主还是自己慢慢调吧

谢谢你,谢谢马老师,问题解决了

machao 发表于 2014-5-23 02:56:23

汗颜,为什么谢我?你花费了时间,可走的是歪路。貌似解决了,只不过是在错误路上走的更远。

STM32本身有I2C硬件接口,偏用IO口模拟,还用大量的软件延时。这样的代码没有太多的实际工程应用价值,只有初学练连手的作用。不知道通过这个过时的代码练手实践,是否真的掌握了I2C的协议,以及基本的MCU应用方法。

页: [1]
查看完整版本: stm32 24c02 接收数据0xff