硬件实现IIC协议读取EEPROM
我TMD也是服了,反正我板子搞了半天也不成功我也不知道为什么,野火STM32-MINI,一直卡EV5,不管了 先代码沾上

工程目录(板子为野火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通讯实验\n"); 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**********************/
硬件实现IIC协议读取EEPROM的更多相关文章
- 第十六章 IIC协议详解+UART串口读写EEPROM
十六.IIC协议详解+Uart串口读写EEPROM 本文由杭电网友曾凯峰根据小梅哥FPGA IIC协议基本概念公开课内容整理并最终编写Verilog代码实现使用串口读写EEPROM的功能. 以下为原文 ...
- IIC协议建模——读写EEPROM
案例采用明德扬设计思想完成.IIC协议是非常常用的接口协议,在电子类岗位招聘要求中经常出现它的身影.关于IIC协议这里只做简要介绍,详细信息请自行百度或查阅相关Datasheet,网上资料非常多.该篇 ...
- 基于STM8的IIC协议--实例篇--时钟模块(DS3231)读取
1. 综述 由上篇博客可知道IIC协议如何用代码实现,本篇博客就不涉及协议内容,只讲解如何使用. 本次的实验传感为:DS3231(时钟模块),对于时钟模块的具体信息我也就不多介绍,大家可以自行度娘,具 ...
- IIC协议理解(转)
目录 IIC协议理解(转) 个人小结记录 (记一下这个就够了) 以下为转载记录 概述 概述 输出级 主设备与从设备 速率 时序 空闲状态 起始位与停止位 数据的有效性 数据的传送 工作过程 主设备向从 ...
- IIC协议解释(转)
IIC协议解释 推荐资源: http://m.elecfans.com/article/574049.html and https://blog.csdn.net/firefl ...
- 【STM32】IIC的基本原理(实例:普通IO口模拟IIC时序读取24C02)(转载)
版权声明:本文为博主原创文章,允许转载,但希望标注转载来源. https://blog.csdn.net/qq_38410730/article/details/80312357 IIC的基本介绍 ...
- IIC协议解释
IIC协议解释 (1)概述 I2C(Inter-Integrated Circuit BUS) 集成电路总线,该总线由NXP(原PHILIPS)公司设计,多用于主控制器和从器件间的主从通信,在小数据量 ...
- IIC协议解析
(1)概述 I2C(Inter-Integrated Circuit BUS) 集成电路总线,该总线由NXP(原PHILIPS)公司设计,多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距 ...
- IIC协议学习笔记
"移植"的重要性:并非所有的电路都得自己设计,到了一定阶段,"移植"也是一种学习能力.--CrazyBingo 转眼间期末又到了,最近开始了所谓的期末总预习,比 ...
随机推荐
- [PKUSC2018]真实排名——线段树+组合数
题目链接: [PKUSC2018]真实排名 对于每个数$val$分两种情况讨论: 1.当$val$不翻倍时,那么可以翻倍的是权值比$\frac{val-1}{2}$小的和大于等于$val$的. 2.当 ...
- vue点击父组件里面的列表动态传值到子组件
<template> <div> 爸爸 <div style="background-color:yellow;margin-top:10px" v- ...
- yum安装nginx添加upstream_check_module模块
下载模块 upstream_check_module 查看yum安装nginx版本信息 # nginx -V nginx version: nginx/1.17.0 built by gcc 4.8. ...
- Vue插槽详解
简介 插槽:简单理解就是组件内部留一个或多个的插槽位置,可供组件传对应的模板代码进去.插槽的出现,让组件变的更加灵活. 一.匿名插槽 // 组件(父) <my-component> < ...
- uni-app和php交互DES加密解密数据
1 uni-app操作 (1) 打开HBuilderX的视图->显示终端 cd 切换到你项目的根目录 执行命令 npm install crypto-js 安装成功后你的项目根目录会生成node ...
- Java 面向对象(四)
代码块 什么是代码块 在类中或方法当中 使用 { } 括起来的一段代码,就称它是一个代码块. 在代码块当中定义的变量我们称是局部变量,在外面是没有办法使用的.这里定义的 a 就是一个局部变量. 代码块 ...
- Qt代码配色VS2015风格
通过本文的方法可以将VS2015的深色主题界面应用到Qt上,对于喜欢VS代码风格配色的人应该会比较有用 效果图: 1. 设置IDE主题 为了配合vs深色的代码编辑背景,将Qt的主题也换成深色版本 2 ...
- 简易的CRM系统案例之SpringMVC+JSP+MySQL+myBatis框架版本
主要对上一版DAO框架的替换hibernate变成myBatis 简易的CRM系统案例之SpringMVC+JSP+MySQL+hibernate框架版本 src/mybatis.xml <?x ...
- Jsoup-基础练习
认识Jsoup 一个解析网页的工具 无论你用什么语言爬虫,都要解析网页,今天,我们用一款常用的网页解析Jsoup,来开启爬虫的第一课 认识网页,认识爬虫,认识你自己 *** 快速上手 了解一个新东西最 ...
- tp5.1 model 方法下的like语句查询
$where_like = ['title','like','%' . $_GET['title'] . '%']; $result_list = $this->model->where( ...