zoukankan      html  css  js  c++  java
  • 硬件实现IIC协议读取EEPROM

    我TMD也是服了,反正我板子搞了半天也不成功我也不知道为什么,野火STM32-MINI,一直卡EV5,不管了 先代码沾上

    1

    2 工程目录(板子为野火STM32 MINI)

    串口相关代码:

    bsp_usart.h

    #ifndef __USART_H
    #define	__USART_H
    
    
    #include "stm32f10x.h"
    #include <stdio.h>
    
    /**
      * 串口宏定义,不同的串口挂载的总线和IO不一样,移植时需要修改这几个宏
    	* 1-修改总线时钟的宏,uart1挂载到apb2总线,其他uart挂载到apb1总线
    	* 2-修改GPIO的宏
      */
    
    // 串口1-USART1
    #define  DEBUG_USARTx                   USART1
    #define  DEBUG_USART_CLK                RCC_APB2Periph_USART1
    #define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd
    #define  DEBUG_USART_BAUDRATE           115200
    
    // USART GPIO 引脚宏定义
    #define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
    #define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
    #define  DEBUG_USART_TX_GPIO_PORT         GPIOA
    #define  DEBUG_USART_TX_GPIO_PIN          GPIO_Pin_9
    #define  DEBUG_USART_RX_GPIO_PORT       GPIOA
    #define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10
    
    #define  DEBUG_USART_IRQ                USART1_IRQn
    #define  DEBUG_USART_IRQHandler         USART1_IRQHandler
    
    void USART_Config(void);
    
    #endif /* __USART_H */

    bsp_usart.c

     

    #include "./usart/bsp_usart.h"
    
    
     /**
      * @brief  USART GPIO 配置,工作参数配置
      * @param  无
      * @retval 无
      */
    void USART_Config(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	USART_InitTypeDef USART_InitStructure;
    
    	// 打开串口GPIO的时钟
    	DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
    
    	// 打开串口外设的时钟
    	DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
    
    	// 将USART Tx的GPIO配置为推挽复用模式
    	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
    
      // 将USART Rx的GPIO配置为浮空输入模式
    	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    	GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
    
    	// 配置串口的工作参数
    	// 配置波特率
    	USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
    	// 配置 针数据字长
    	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(DEBUG_USARTx, &USART_InitStructure);
    
    	// 使能串口
    	USART_Cmd(DEBUG_USARTx, ENABLE);
    }
    
    
    ///重定向c库函数printf到串口,重定向后可使用printf函数
    int fputc(int ch, FILE *f)
    {
    		/* 发送一个字节数据到串口 */
    		USART_SendData(DEBUG_USARTx, (uint8_t) ch);
    
    		/* 等待发送完毕 */
    		while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
    
    		return (ch);
    }
    
    ///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
    int fgetc(FILE *f)
    {
    		/* 等待串口输入数据 */
    		while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);
    
    		return (int)USART_ReceiveData(DEBUG_USARTx);
    }
    

    bsp_i2c_ee.h

    #ifndef __I2C_EE_H
    #define	__I2C_EE_H
    
    
    #include "stm32f10x.h"
    #include "bsp_usart.h"
    
    #define  EEPROM_ADDR  0xA0
    
    
    void I2C_EE_Config(void);
    void EEPROM_Byte_Write(uint8_t addr,uint8_t data);
    void EEPROM_Page_Write(uint8_t addr,uint8_t *data,uint8_t numByteToWrite);
    void EEPROM_Read(uint8_t addr,uint8_t *data,uint8_t numByteToRead);
    void EEPROM_WaitForWriteEnd(void);
    
    
    #endif /* __I2C_EE_H */
    

    bsp_i2c_ee.c

    #include "bsp_i2c_ee.h"
    
    
    
    void I2C_EE_Config(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	I2C_InitTypeDef  I2C_InitStructure;
    
    	// 打开IIC GPIO的时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    	// 打开IIC 外设的时钟
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    
    	// 将IIC SCL SDA的GPIO配置为推挽复用模式
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    
    
    	// 配置IIC的工作参数
    	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable  ;//使能应答
    	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit ;//使用7位地址模式
    	I2C_InitStructure.I2C_ClockSpeed = 400000; //配置SCL时钟频率
    	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2 ;
    	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C ;
    	I2C_InitStructure.I2C_OwnAddress1 = 0x5f; //这是STM32 IIC自身设备地址,只要是总线上唯一即可
    
    	I2C_Init(I2C1,&I2C_InitStructure);
    
    	// 使能串口
    	I2C_Cmd (I2C1, ENABLE);
    }
    
    
    //向EEPROM写入一个字节
    
    void EEPROM_Byte_Write(uint8_t addr,uint8_t data)
    {
    	//产生起始信号
    	I2C_GenerateSTART(I2C1,ENABLE);
    
    	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
    
    	//EV5事件被检测到,发送设备地址
    	I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);
    
      while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) == ERROR);
    
    	//EV6事件被检测到,发送要操作的存储单元地址
    	I2C_SendData (I2C1,addr);
    
    	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING ) == ERROR);
    
      //EV8事件被检测到,发送要存储的数据
    	I2C_SendData (I2C1,data);
    
    	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED ) == ERROR);
    
    	//数据传输完成
    	I2C_GenerateSTOP(I2C1,ENABLE);
    
    }
    
    
    
    //向EEPROM写入多个字节(页写入),每次写入不能超过8个字节
    
    void EEPROM_Page_Write(uint8_t addr,uint8_t *data,uint8_t numByteToWrite)
    {
    	//产生起始信号
    	I2C_GenerateSTART(I2C1,ENABLE);
    
    	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
    
    	//EV5事件被检测到,发送设备地址
    	I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);
    
      while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) == ERROR);
    
    	//EV6事件被检测到,发送要操作的存储单元地址
    	I2C_SendData (I2C1,addr);
    
    	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING ) == ERROR);
    
    
    	while(numByteToWrite)
    	{
    		//EV8事件被检测到,发送要存储的数据
    		I2C_SendData (I2C1,*data);
    
    		while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED ) == ERROR);
    
    		data++;
    		numByteToWrite--;
    
    	}
    	//数据传输完成
    	I2C_GenerateSTOP(I2C1,ENABLE);
    
    }
    
    
    
    //从EEPROM读取数据
    
    void EEPROM_Read(uint8_t addr,uint8_t *data,uint8_t numByteToRead)
    {
    	//产生起始信号
    	I2C_GenerateSTART(I2C1,ENABLE);
    
    	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
    
    	//EV5事件被检测到,发送设备地址
    	I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);
    
      while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) == ERROR);
    
    	//EV6事件被检测到,发送要操作的存储单元地址
    	I2C_SendData (I2C1,addr);
    
    	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING ) == ERROR);
    
    
    	//第二次起始信号
    	//产生起始信号
    	I2C_GenerateSTART(I2C1,ENABLE);
    
    	while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR);
    
    	//EV5事件被检测到,发送设备地址
    	I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Receiver);
    
      while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) == ERROR);
    
    
    	while(numByteToRead)
    	{
    		if(numByteToRead == 1)
    		{
    			//如果为最后一个字节
    			I2C_AcknowledgeConfig (I2C1,DISABLE);
    		}
    
    		//EV7事件被检测到	
    		while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED ) == ERROR);
    
    		//EV7事件被检测到,即数据寄存器有新的有效数据	
    		*data = I2C_ReceiveData(I2C1);
    
    		data++;
    
    		numByteToRead--;
    
    	}
    
    
    	//数据传输完成
    	I2C_GenerateSTOP(I2C1,ENABLE);
    
    	//重新配置ACK使能,以便下次通讯
    	I2C_AcknowledgeConfig (I2C1,ENABLE);
    
    }
    
    
    //等待EEPROM内部时序完成
    void EEPROM_WaitForWriteEnd(void)
    {
    
    	do
    	{
    		//产生起始信号
    		I2C_GenerateSTART(I2C1,ENABLE);
    
    		while(I2C_GetFlagStatus (I2C1,I2C_FLAG_SB) == RESET);
    
    		//EV5事件被检测到,发送设备地址
    		I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);
    	}
    	while(I2C_GetFlagStatus (I2C1,I2C_FLAG_ADDR) == RESET );
    
    	//EEPROM内部时序完成传输完成
    	I2C_GenerateSTOP(I2C1,ENABLE);
    }

    main.c

    #include "stm32f10x.h"
    #include "./usart/bsp_usart.h"
    #include "./i2c/bsp_i2c_ee.h"
    
    
    uint8_t readData[10]={0};
    uint8_t writeData[8]={4,5,6,7,8,9,10,11};
     /**
      * @brief  主函数
      * @param  无
      * @retval 无
      */
    int main(void)
    {
    	 uint8_t i=0;
       USART_Config();
    	 printf("这是一个IIC通讯实验
    ");
    
    	 I2C_EE_Config();
       //向 EEPROM 11地址写入0x55,
       EEPROM_Byte_Write(11,0x55);
    	 EEPROM_WaitForWriteEnd();
    	 //读出 EEPROM 11地址的内容,保存到readData中(数组的第一个址位)
    	 EEPROM_Read(11,readData,1);
    	 printf("%x",readData[0]);
    
    		//addr%8 == 0 ,即为地址对齐
    	EEPROM_Page_Write(16,writeData,8);
    
    	//等待写入操作完成
    	EEPROM_WaitForWriteEnd();
    
    	//读取数据
    	EEPROM_Read(16,readData,8);
    	for(i=0;i<8;i++)
    	{
    		printf("%d ",readData[i]);
    	}
        while(1);
    }
    /*********************************************END OF FILE**********************/
  • 相关阅读:
    AI大语音(十二)——WFST解码器(下)(深度解析)
    AI大语音(十一)——WFST解码器(上)(深度解析)
    AI大语音(十)——N-gram语言模型(深度解析)
    AI大语音(九)——基于GMM-HMM的连续语音识别系统
    AI大语音(八)——GMM-HMM声学模型
    AI大语音(七)——基于GMM的0-9语音识别系统
    AI大语音(五)——隐马尔科夫模型(HMM)
    AI大语音(四)——MFCC特征提取
    HTTP 协议入门
    List of Unix commands
  • 原文地址:https://www.cnblogs.com/wenshinlee/p/8995023.html
Copyright © 2011-2022 走看看