硬件实现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 转眼间期末又到了,最近开始了所谓的期末总预习,比 ...
随机推荐
- Tkinter 之Scale滑块标签
一.参数说明 语法 作用 Scale(window, label="滑块") 滑块标题 Scale(window, label="滑块", from_=0) 滑 ...
- JAVA基础知识|java虚拟机(JVM)
一.JVM简介 java语言是跨平台的,兼容各种操作系统.实现跨平台的基石就是虚拟机(JVM),虚拟机不是跨平台的,所以不同的操作系统需要安装不同的jdk版本(jre=jvm+类库:jdk=jre+开 ...
- 2018-2019-2 网络对抗技术 20165231 Exp7 网络欺诈防范
实践内容(3.5分) 本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法.具体实践有 (1)简单应用SET工具建立冒名网站 (1分) (2)ettercap DNS spoof ...
- 我的公众号:WebHub
欢迎各位小可爱关注我的公众号WebHub(ID:myWebHub),公众号不定期更新软件行业的总结性文章,内容包括行业趋势和软件哲学,文章不谈技术只谈思想,满满干货! 此外,公众号文章同步CSDN博客 ...
- 黑马vue---33、vue-resource 实现 get, post, jsonp请求
黑马vue---33.vue-resource 实现 get, post, jsonp请求 一.总结 一句话总结: vue-resource使用非常非常非常简单:this.$http.get('htt ...
- Windows安装Centos7双系统后Windows启动项消失
原文: https://www.cnblogs.com/xinglichao/p/9999049.html https://blog.csdn.net/yingzinanfei/article/det ...
- 如何在vue-cli 3.x中使用jquery
由于项目需求要使用jquery,结果各种引用都不济于事. 最后在网上找到了答案,现把它记录一下,给有需要者. 首先下载 jquery. cnpm install jquery --save-dev 方 ...
- 阶段5 3.微服务项目【学成在线】_day08 课程图片管理 分布式文件系统_06-分布式文件系统研究-fastDFS安装及配置文件说明
3 fastDFS入门 3.1fastDFS安装与配置 3.1.1 导入虚拟机 对fastDFS的安装过程不要求学生掌握,可以直接导入老师提供虚拟机. 1.使用Vmware打开虚拟机配置文件“Cent ...
- Qt编写自定义控件52-颜色下拉框
一.前言 这个控件写了很久了,元老级别的控件之一,开发之初主要是自己的好几个项目要用到,比如提供一个颜色下拉框设置对应的曲线或者时间颜色,视频监控项目中经常用到的OSD标签设置,这个控件的难度系数接近 ...
- Chrome浏览器控制网速的方法