完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
公司最近打算采用ST的单片机,其他单片机工程师比较忙,好吧,我只是个打杂的,于是被抓壮丁来处理,目标是使用I2C总线和一外设通信,想想也没啥难度。 于是,我参考网上的教程,配置了Keil的开发环境,参照了Keil给的I2C例子,写了个I2C通信代码,可是无法通信,非常着急,希望xdjm路过给打个赏,给找找虫子,非常感谢!
简单的说是这样的,使用I2C2和外设相连,(I2C2连端口复用都没得) /* Includes ------------------------------------------------------------------*/#include "STM32f10x_lib.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ #define I2C2_SLAVE_ADDRESS7 0x00 //I2C2的地址,7位寻址 #define ADV7611_SLAVE_ADDRESS7 0x98 //ADV7611的地址,7位寻址 #define BufferSize 2 //u16 #define ClockSpeed 400000 //2MHz u8 I2C2_Buffer_Tx[BufferSize]={0,0}; u8 I2C2_Buffer_Rx[BufferSize]={0,0}; /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ I2C_InitTypeDef I2C_InitStructure; EXti_InitTypeDef EXTI_InitStructure; ErrorStatus HSEStartUpStatus; //自定义的配置功能函数 /* Private functions ---------------------------------------------------------*/ void RCC_Configuration(void); //时钟,使用某功能前必须先激活该模块的时钟 void GPIO_Configuration(void); //GPIO配置信息,使用哪种端口,输入,输出,和初始值 void NVIC_Configuration(void); //中断配置信息 void ADV7611_Write(u8* pBuffer, u16 WriteAddrOffset, u16 NumByteToWrite); //写ADV7611一段数据,字节对齐 void ADV7611_Read(u8* pBuffer, u16 ReadAddrOffset, u16 NumByteToRead); //读ADV7611一段数据,字节对齐 void delay_ms(u16 time);//非精确的延时函数 int main(void)//主过程函数 { /* System clocks configuration ---------------------------------------------*/ RCC_Configuration(); /* NVIC configuration ------------------------------------------------------*/ NVIC_Configuration(); /* GPIO configuration ------------------------------------------------------*/ GPIO_Configuration(); //reset ADV7611 chips frist GPIO_ResetBits(GPIOA,GPIO_Pin_9); delay_ms(5); GPIO_SetBits(GPIOA,GPIO_Pin_9); delay_ms(5); /* I2C configuration ------------------------------------------------------*/ I2C_Configuration(); I2C2_Buffer_Tx[0]=0x00; I2C2_Buffer_Tx[1]=0x00; ADV7611_Write(I2C2_Buffer_Tx, 0x400, 2); while (1) { } } void RCC_Configuration(void) { /* RCC system reset(for debug purpose) */ RCC_DeInit(); /* Enable HSE */ RCC_HSEConfig(RCC_HSE_ON); /* Wait till HSE is ready */ HSEStartUpStatus = RCC_WaitForHSEStartUp(); if(HSEStartUpStatus == SUCCESS) { /* Enable Prefetch Buffer */ FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /* Flash 2 wait state */ FLASH_SetLatency(FLASH_Latency_2); /* HCLK = SYSCLK */ RCC_HCLKConfig(RCC_SYSCLK_Div1); /* PCLK2 = HCLK */ RCC_PCLK2Config(RCC_HCLK_Div1); /* PCLK1 = HCLK/2 */ RCC_PCLK1Config(RCC_HCLK_Div2); /* PLLCLK = 8MHz * 9 = 72 MHz */ RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); /* Enable PLL */ RCC_PLLCmd(ENABLE); /* Wait till PLL is ready */ while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) { } /* Select PLL as system clock source */ RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* Wait till PLL is used as system clock source */ while(RCC_GetSYSCLKSource() != 0x08) { } } /* Enable peripheral clocks --------------------------------------------------*/ /* GPIOB Periph clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /* GPIOA Periph clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* AFIO clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); /* I2C1 and I2C2 Periph clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 | RCC_APB1Periph_I2C2, ENABLE); } /******************************************************************************* * Function Name : GPIO_Configuration * Description : Configures the different GPIO ports. * Input : None * Output : None * Return : None *******************************************************************************/ void GPIO_Configuration(void) //配置GPIO的管脚功能 { GPIO_InitTypeDef GPIO_InitStructure; //初始化的结构 /* Configure I2C1 pins: SCL and SDA ----------------------------------------*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_Init(GPIOB, &GPIO_InitStructure); /* Configure I2C2 pins: SCL and SDA ----------------------------------------*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_Init(GPIOB, &GPIO_InitStructure); } 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 } void I2C_Configuration(void) //配置GPIO的管脚功能 { //配置I2C1的初始化参数 /* I2C1 configuration ------------------------------------------------------*/ I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//激活ACK I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//7bit的地址模式 I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;//设置I2C的时钟频率 /* Enable I2C1 and I2C2 ----------------------------------------------------*/ I2C_Cmd(I2C1, ENABLE); I2C_Init(I2C1, &I2C_InitStructure); //初始化I2C1 /* I2C2 configuration ------------------------------------------------------*/ I2C_InitStructure.I2C_OwnAddress1 = I2C2_SLAVE_ADDRESS7;//设置I2C2的地址信息,其他的配置信息和I2C1相同 I2C_Cmd(I2C2, ENABLE); I2C_Init(I2C2, &I2C_InitStructure);//初始化I2C2 } void ADV7611_Write(u8* pBuffer, u16 WriteAddrOffset, u16 NumByteToWrite) { u8 Offset_MSB = 0; u8 Offset_LSB = 0; /*wait I2C idle statues */ while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY)); /* Send I2C2 START condition */ I2C_GenerateSTART(I2C2, ENABLE); //I2C2产生开始信号(S),进入主发送模式 /* Test on I2C2 EV5 and clear it */ while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)); //产生开始信息后,需要检测是否有EV5事件通知 /* Send MDIN380 slave Address for write */ I2C_Send7bitAddress(I2C2, ADV7611_SLAVE_ADDRESS7 , I2C_Direction_Transmitter);//发送从设备的地址,和传输方向(R?W?) /* Test on EV6 and clear it */ while(! I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //I2C_Cmd(I2C2, ENABLE); /*with 16bit BUS Mode,then MSB(A10...A8),LSB(A7...A0)*/ Offset_MSB = (u8) ((WriteAddrOffset>>8)&0x0F); Offset_LSB = (u8) (WriteAddrOffset&0x00FF); /* Send the ADV7611's internal address (MSB) to write to */ I2C_SendData(I2C2, Offset_MSB); /* Test on EV8 and clear it */ while(! I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /* Send the ADV7611's internal address (LSB) to write to */ I2C_SendData(I2C2, Offset_LSB); /* Test on EV8 and clear it */ while(! I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /* While there is data to be 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)); } /* Send STOP condition */ I2C_GenerateSTOP(I2C2, ENABLE); } void delay_ms(u16 time) { u16 i=0; while(time--) { i=12000; while(i--); } } |
|
相关推荐
12个回答
|
|
楼上说的正确,我们都是用的IO模拟I2C通信。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TOPCB 发表于 2019-3-21 10:42 谢谢,目前使用模拟器抓取波形,使用的模拟io的I2C方式,非常感谢 |
|
|
|
我是用IO模拟的I2C,你可以试试。
|
|
|
|
|
|
|
|
ADV7611有个论坛,上面有人贴出了完整代码,可以参考,我们这边项目还需要用MDIN380显示输出,所以没有办法验证正确性,我把代码转给你,是参考的 |
|
|
|
谢谢,我已经按照你们的Demo,写出可以正确I2C通信的代码,非常感谢! |
|
|
|
学习了
|
|
|
|
重点看下应答信号
|
|
|
|
我也是用不好STM32的硬件I2C,只能模拟使用!
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
2105 浏览 1 评论
AD7686芯片不传输数据给STM32,但是手按住就会有数据。
1941 浏览 3 评论
4537 浏览 0 评论
如何解决MPU-9250与STM32通讯时,出现HAL_ERROR = 0x01U
2084 浏览 1 评论
hal库中i2c卡死在HAL_I2C_Master_Transmit
2599 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 19:08 , Processed in 0.777053 second(s), Total 97, Slave 79 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号