历史上的今天
今天是:2025年08月12日(星期二)
2019年08月12日 | STM32-(20):I2C通信(实验:读写EEPROM)
2019-08-12 来源:eefocus
硬件电路连接
底板上的 I2C 接口

A0、A1是用来确定器件的地址的。
排针上的引脚图:
核心板上的引脚图:
通过I2C总线实现对EEPROM的读写操作的准备工作:
1、掌握芯片(目标对象)特性,才能对其正确的读和写。
2、掌握 I2C 通信,读写过程需要用到。
3、Cortex的一些操作,编程方法。
实验内容:通过I2C总线实现对EEPROM的读写操作
main.c
#include"stm32f10x_lib.h"
#include"IIC.h"
/*------------函数的声明---------------*/
void Delay_MS(u16 dly);
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
/**********************************TEST*******************************/
int main(void)
{
#ifdef DEBUG
debug();
#endif
u8 Tab[]="hello";
u8 ReadTab[5];
RCC_Configuration();
I2C_Configuration();
NVIC_Configuration(); //中断配置
GPIO_Configuration();
GPIO_SetBits(GPIOA, GPIO_Pin_3);
//这里将 Tab的5个值写入 EEPROMZ中去,然后从EEPROM中读取出来存入ReadTab 中去,
//然后比较Tab 和 EEPROM ,若内容一致,则说明读写都成功。
while(1)
{
// I2C_PageWrite(&Tab[0],0xA0,5);
I2C_BufferWrite(&Tab[0],0xA0,5);
Delay_MS(20);
I2C_BufferRead(&ReadTab[0],0xA0,5);
Delay_MS(20);
}
}
/*******************************************************************************
* Function Name : Delay_Ms
* Description : delay 1 ms.
* Input : dly (ms)
* Output : None
* Return : None
*******************************************************************************/
void Delay_MS(u16 dly)
{
u16 i,j;
for(i=0;i } /******************************************************************************* * Function Name : RCC_Configuration * Description : Configures the different system clocks. * Input : None * Output : None * Return : None *******************************************************************************/ void RCC_Configuration(void) { //----------使用外部RC晶振----------- RCC_DeInit(); //初始化为缺省值 RCC_HSEConfig(RCC_HSE_ON); //使能外部的高速时钟 while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); //等待外部高速时钟使能就绪 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //Enable Prefetch Buffer FLASH_SetLatency(FLASH_Latency_2); //Flash 2 wait state RCC_HCLKConfig(RCC_SYSCLK_Div1); //HCLK = SYSCLK RCC_PCLK2Config(RCC_HCLK_Div1); //PCLK2 = HCLK RCC_PCLK1Config(RCC_HCLK_Div2); //PCLK1 = HCLK/2 RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); //PLLCLK = 8MHZ * 9 =72MHZ RCC_PLLCmd(ENABLE); //Enable PLLCLK while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //Wait till PLLCLK is ready RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //Select PLL as system clock while(RCC_GetSYSCLKSource()!=0x08); //Wait till PLL is used as system clock source //---------打开相应外设时钟-------------------- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能APB2外设的GPIOA的时钟 } /******************************************************************************* * Function Name : GPIO_Configuration * Description : 初始化GPIO外设 * Input : None * Output : None * Return : None *******************************************************************************/ void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //选择PA.3 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率为50MHZ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //输出模式为推挽输出 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化GPIOA寄存器 } /******************************************************************************* * Function Name : NVIC_Configuration * Description : Configures the nested vectored interrupt controller. * Input : None * Output : None * Return : None *******************************************************************************/ void NVIC_Configuration(void) { // NVIC_InitTypeDef NVIC_InitStructure; #ifdef VECT_TAB_RAM /* Set the Vector Table base location at 0x20000000 */ NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); #else /* VECT_TAB_FLASH */ /* Set the Vector Table base location at 0x08000000 */ NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); #endif } IIC.c /******************************************************************* 本实验使用CAT24WC16: CAT24WC16是CATALSYT公司生产的串行电可擦除的可编程存储器。其内部共有128页,每一页 为16字节,每一个字节8位。CAT24WC16以一个字节为一个存储单元,共有2K个存储单元。因此任一 存储单位地址为11位(A0~A11),地址范围为0x00~0x7FF(2K地址范围)。 *******************************************************************/ #include"stm32f10x_lib.h" #include"IIC.h" #define EEPROM_ADDRESS 0xA0 #define I2C2_SLAVE_ADDRESS7 0xA0 #define I2C_Speed 200000 #define I2C_PageSize 16 void I2C_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; //1、开时钟 GPIOB,I2C2 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); //2、PB10 PB11 复用开漏输出 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); //3、I2C 配置 I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //设置I2C为I2C模式 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //I2C快速模式 I2C_InitStructure.I2C_OwnAddress1 = I2C2_SLAVE_ADDRESS7; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //使能应答 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed = I2C_Speed; //4、使能I2C模块 I2C_Cmd(I2C2,ENABLE); I2C_Init(I2C2,&I2C_InitStructure); } void I2C2_Init(void) { I2C_Configuration(); } //字节写 void I2C_ByteWrite(u8 *pBuffer,u8 WriteAddr) { I2C_WaitEepromStandbyState(); /* [1]Send Start Condition 发送起始信号*/ I2C_GenerateSTART(I2C2,ENABLE); /* [2]Test On EV5 and clear it 起始信号已发送并清除该事件 */ while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT)); /* [3]Send EEPROM address for write 发送器件地址*/ I2C_Send7bitAddress(I2C2,EEPROM_ADDRESS,I2C_Direction_Transmitter); /* [4]Test on Ev6 and clear it 地址发送结束 */ while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); /* [5]Send EEPROM's internal address to write 发送器件内部写入地址 */ I2C_SendData(I2C2,WriteAddr); /* [6]Test on EV8 _1 and clear it 移位寄存器空 */ while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /* [7]Send the byte to be writeen 发送数据*/ I2C_SendData(I2C2,*pBuffer); /* [8]Test on EV8 and clear it 发送缓冲区空*/ while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /* [9]Send STOP condition 发送停止信号 */ I2C_GenerateSTOP(I2C2,ENABLE); } //页写 void I2C_PageWrite(u8 *pBuffer,u8 WriteAddr,u8 NumByteToWrite) { I2C_WaitEepromStandbyState(); /*[1]Send START condition 发送起始条件*/ I2C_GenerateSTART(I2C2,ENABLE); /*[2]Test on EV5 and clear it 起始信号发送是否成功*/ while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT)); /*[3]Send EEPROM address for write 发送器件地址*/ //EEPROM_ADDRESS 表示 EEPROM器件的地址 I2C_Send7bitAddress(I2C2,EEPROM_ADDRESS,I2C_Direction_Transmitter); /*[4]Test on EV6 and clear it 发送器件地址是否成功*/ while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); /*[5]Send EEPROM'S internal address to write to 发送数据的写入首地址*/ //WriteAddr 表示EEPROM器件内部的读写地址(器件内部的存储地址) I2C_SendData(I2C2,WriteAddr); /*[6]Test on EV8 and clear it 发送内部地址是否成功*/ while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /*[7]Send data to Written 发送数据*/ while(NumByteToWrite--) { /*Send the current byte 发送当前一个字节*/ I2C_SendData(I2C2,*pBuffer); /* Point to the next byte to be written 地址++*/ pBuffer++; /*Test on EV8 and clear it 发送缓冲区是否为空*/ while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED)); } /*[8]Send STOP condition 发送停止信号*/ (发送完成之后发送停止信号) I2C_GenerateSTOP(I2C2,ENABLE); } //写数据:参数1:即将被写入的源数据;参数2:写入的目的地址;参数3:写入数据的大小; void I2C_BufferWrite(u8 *pBuffer,u8 WriteAddr,u16 NumByteToWrite) { u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0; Addr = WriteAddr % I2C_PageSize; //得到页地址 I2C_PageSize = 16, count = I2C_PageSize - Addr; NumOfPage = NumByteToWrite / I2C_PageSize; NumOfSingle = NumByteToWrite % I2C_PageSize; I2C_WaitEepromStandbyState(); //等待EEPROM处于空闲状态 /* If WriteAddr is I2C_PageSize aligned */ if(Addr == 0) { /* If NumByteToWrite < I2C_PageSize */ if(NumOfPage == 0) { I2C_PageWrite(pBuffer, WriteAddr, NumOfSingle); I2C_WaitEepromStandbyState(); } /* If NumByteToWrite > I2C_PageSize */ else { while(NumOfPage--) { I2C_PageWrite(pBuffer, WriteAddr, I2C_PageSize); I2C_WaitEepromStandbyState(); WriteAddr += I2C_PageSize; pBuffer += I2C_PageSize; } if(NumOfSingle!=0) { I2C_PageWrite(pBuffer, WriteAddr, NumOfSingle); I2C_WaitEepromStandbyState(); } } } /* If WriteAddr is not I2C_PageSize aligned */ else { /* If NumByteToWrite < I2C_PageSize */ if(NumOfPage== 0) { I2C_PageWrite(pBuffer, WriteAddr, NumOfSingle); I2C_WaitEepromStandbyState(); } /* If NumByteToWrite > I2C_PageSize */ else { NumByteToWrite -= count; NumOfPage = NumByteToWrite / I2C_PageSize; NumOfSingle = NumByteToWrite % I2C_PageSize; if(count != 0)
史海拾趣
|
近几年来,高清已经成为众多安防厂家追求的趋势,金融、交通等领域需求的增加也为安防高清日渐上升的地位奠定了基础。那么,究竟是什么原因促进了安防高清的快速发展?是不是所有的安防厂商都可以发展高清产品?百万高清在发展的过程中又遇到了哪些困 ...… 查看全部问答> |
|
我移植了UCOS II+UCGUI 3.90A到STM32F103ZE上,并用如下方法建立了一个定时器,结果定时器仅响应一次,请问是什么原因啊? GUI_TIMER_HANDLE g_TimeTimer=NULL; g_TimeTimer=GUI_TIMER_Create((GUI_TIMER_CALLBACK *)RefreshTime,1000,0,0) ...… 查看全部问答> |
|
这是利尔达公司为Ti代理所做的一个设计,用来检测非法入侵及周界安全。当玻璃门、窗被打破时,产生的高频信号被麦克风检测到,通过单片机对信号进行分析,再进行报警。 [ 本帖最后由 鑫海宝贝 于 2011-10-12 09:34 编辑 ]… 查看全部问答> |
|
/*#include \"msp430g2553.h\"unsigned char num;void main(){ // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; BCSCTL ...… 查看全部问答> |




