历史上的今天
返回首页

历史上的今天

今天是:2025年03月11日(星期二)

正在发生

2021年03月11日 | STM32的i2c容易出的问题 和l3g4200d例程

2021-03-11 来源:eefocus

调试了一晚上,终于一点点把stm32可怕的i2c消灭了,这里分享一下遇到的问题。

最严重的一次卡住居然是在这句话上

/* Send START condition */

I2C_GenerateSTART(I2C1, ENABLE);

/* Test on EV5 and clear it */

while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

执行到第二句就怎么也过不去了,后来才很气愤的发现这是stm32的硬件bug,把fsmc关掉才能使用i2c1的非重影射引脚,关掉以后一切正常。害得我干瞪了两个小时屏幕。


第二次被卡住是在

I2C_Send7bitAddress(I2C1, 0xD2, I2C_Direction_Transmitter);

while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

错误的原因是传输的地址要左移一位。虽然地址是7位的,但是必须在后面而不是前面补零,变成8位地址再传递。


第三次是在

I2C_GenerateSTOP(I2C1, ENABLE);//产生 I2Cx传输 STOP条件

while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));

原因是必须要先产生终止再检查数据。仔细读手册就解决了这个问题


已经凌晨一点了,终于长舒一口气。这里把代码贴上来,是一个调试陀螺仪l3g4200d的程序,直接调用GYRO_Test()即可,但是必须先调用GYRO_Init(),初始化GPIO和RCC,并添加相应的头文件。


#define WHO_AM_I 0x0F


#define CTRL_REG1 0x20


#define CTRL_REG2 0x21


#define CTRL_REG3 0x22


#define CTRL_REG4 0x23


#define CTRL_REG5 0x24


#define REFERENCE 0x25


#define OUT_TEMP 0x26


#define STATUS_REG 0x27


#define OUT_X_L 0x28


#define OUT_X_H 0x29


#define OUT_Y_L 0x2A


#define OUT_Y_H 0x2B


#define OUT_Z_L 0x2C


#define OUT_Z_H 0x2D


#define FIFO_CTRL_REG 0x2E


#define FIFO_SRC_REG 0x2F


#define INT1_CFG 0x30


#define INT1_SRC 0x31


#define INT1_TSH_XH 0x32


#define INT1_TSH_XL 0x33


#define INT1_TSH_YH 0x34


#define INT1_TSH_YL 0x35


#define INT1_TSH_ZH 0x36


#define INT1_TSH_ZL 0x37


#define INT1_DURATION 0x38










void I2C_Configuration(void)


{


I2C_InitTypeDef I2C_InitStructure;




I2C_DeInit(I2C1);


/* I2C configuration */


I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;


I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;


I2C_InitStructure.I2C_OwnAddress1 = 0xD2;


I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;


I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;


I2C_InitStructure.I2C_ClockSpeed = 400000;




/* I2C Peripheral Enable */


I2C_Cmd(I2C1, ENABLE);


/* Apply I2C configuration after enabling it */


I2C_Init(I2C1, &I2C_InitStructure);


}






void GYRO_Write(INT8U addr, INT8U data)//write a byte to gyroscope


{


int dummy;


/* Send STRAT condition */


I2C_GenerateSTART(I2C1, ENABLE);


/* Test on EV5 and clear it */


while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);


/* Send EEPROM address for write */


dummy=I2C1->SR1;


I2C_Send7bitAddress(I2C1, 0xD2, I2C_Direction_Transmitter);


/* Test on EV6 and clear it */


while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));


/* Send the EEPROM's internal address to write to */


I2C_SendData(I2C1, addr);


/* Test on EV8 and clear it */


while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));


/* Send the byte to be written */


I2C_SendData(I2C1, data);


/* Test on EV8 and clear it */


while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));


/* Send STOP condition */


I2C_GenerateSTOP(I2C1, ENABLE);


}






INT8U GYRO_Read(INT8U addr)//read a byte from gyroscope


{


INT8U data;


/* Send START condition */


I2C_GenerateSTART(I2C1, ENABLE);


/* Test on EV5 and clear it */


while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));


/* In the case of a single data transfer disable ACK before reading the data */


I2C_AcknowledgeConfig(I2C1, DISABLE);


/* Send EEPROM address for write */


I2C_Send7bitAddress(I2C1, 0xD2, I2C_Direction_Transmitter);


/* Test on EV6 and clear it */


while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));


/* Send the EEPROM's internal address to write to */


I2C_SendData(I2C1, addr);


/* Test on EV8 and clear it */


while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));


/* Send STRAT condition a second time */


I2C_GenerateSTART(I2C1, ENABLE);


/* Test on EV5 and clear it */


while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));


/* Send EEPROM address for read */


I2C_Send7bitAddress(I2C1, 0xD2, I2C_Direction_Receiver);


/* Test on EV6 and clear it */


while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));


/* Send STOP Condition */


I2C_GenerateSTOP(I2C1, ENABLE);


/* Test on EV7 and clear it */


while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));


/* Read a byte from the EEPROM */


data = I2C_ReceiveData(I2C1);




return data;


}








void GYRO_Init(){


I2C_Configuration();


GYRO_Write(CTRL_REG1, 0xEF);


GYRO_Write(CTRL_REG2, 0x00);


GYRO_Write(CTRL_REG3, 0x08);


GYRO_Write(CTRL_REG4, 0x10);


GYRO_Write(CTRL_REG5, 0x00);




}




void GYRO_Test(){


int value1=0,value2=0,value3=0;




value1= GYRO_Read(OUT_X_H)*0x100 + GYRO_Read(OUT_X_L);


if(value1 > 0x7FFF)


value1=value1-0x10000;


value2= GYRO_Read(OUT_Y_H)*0x100 + GYRO_Read(OUT_Y_L);


if(value2 > 0x7FFF)


value2=value2-0x10000;


value3= GYRO_Read(OUT_Z_H)*0x100 + GYRO_Read(OUT_Z_L);


if(value3 > 0x7FFF)


value3=value3-0x10000;




printf("%d %d %dn",value1,value2,value3);


}



运行结果(串口接到的部分数据):

20 33 -51

16 15 -60

19 36 -74

51 -227 -29

-6 34 -32

23 -252 -61

5 26 -40

16 36 -75

34 48 -52

-2 27 -35


推荐阅读

史海拾趣

Aeroflex公司的发展小趣事

Aeroflex是一家提供高性能测试和测量解决方案的公司,在航空航天、国防、通信和工业等领域拥有广泛的应用。以下是Aeroflex公司发展的五个相关故事:

  1. 公司成立和早期发展: Aeroflex公司成立于1973年,最初是一家由David King在新泽西州创建的小型创业公司,专注于为航空航天和国防行业提供测试和测量设备。随着公司在测试领域的技术积累和市场认可,其业务逐渐扩大,开始在全球范围内提供解决方案。

  2. 技术创新和产品发展: Aeroflex致力于技术创新,不断推出符合行业标准和客户需求的新产品。公司在射频和微波测试领域取得了突破,推出了一系列高性能测试仪器和系统,包括信号发生器、频谱分析仪和网络分析仪等,为客户提供全面的测试解决方案。

  3. 全球扩张和市场拓展: 随着市场需求的增长和业务规模的扩大,Aeroflex逐步在全球范围内建立了广泛的销售和服务网络。公司在美国、欧洲、亚洲和其他地区设立了多个分支机构和办事处,以加强对客户的支持和服务,并拓展新的市场领域。

  4. 公司并购和战略合作: 为加速业务增长和拓展技术能力,Aeroflex通过并购和战略合作不断扩大业务范围。公司先后收购了多家具有先进技术和市场地位的企业,加强了在航空航天、国防和通信等领域的竞争实力。

  5. 成为关键行业供应商: 长期以来,Aeroflex凭借卓越的技术和服务,成为航空航天、国防、通信和工业等关键行业的重要供应商之一。公司在测试和测量领域的领先地位得到了进一步巩固,为客户提供了高品质、可靠的产品和解决方案,赢得了良好的声誉和市场口碑。

DIPTRONICS MANUFACTURING INC公司的发展小趣事

为了降低成本、提高生产效率,圜达实业不断进行垂直整合。公司自主设计和生产自动组装机、模具和工具等生产设备,实现了从原材料采购到成品供应的全程控制。这种垂直整合的模式使公司在保证产品品质的同时,也降低了生产成本,提高了市场竞争力。

Electro Adapter Inc公司的发展小趣事

作为一家以技术为核心的企业,EA公司始终将技术创新作为公司发展的重中之重。公司不断引进新技术、新工艺,加强与高校、科研机构的合作,共同研发具有自主知识产权的新产品。在智能电源适配器领域,EA公司率先推出了一系列具有智能化、网络化功能的产品,引领了行业潮流。这些产品的推出不仅提高了公司的市场竞争力,也为客户提供了更加便捷、高效的使用体验。

创世(CS)公司的发展小趣事

作为一家有社会责任感的企业,创世公司始终关注环境保护和可持续发展。公司积极推广绿色生产技术和资源循环利用方案,减少生产过程中的能源消耗和废弃物排放。同时,创世公司还积极参与社会公益活动,为社会和环境贡献自己的力量。这种对社会责任的关注和担当使得创世公司在电子行业中树立了良好的形象。

DAPAudio公司的发展小趣事

DAPAudio公司自成立以来,一直将技术创新作为公司发展的核心动力。在音频处理领域,DAPAudio率先推出了基于先进算法的数字音频处理器,其独特的音质优化技术迅速赢得了市场的认可。随着技术的不断迭代和更新,DAPAudio的产品逐渐在高端音频市场占据了一席之地。

DIOTEC公司的发展小趣事

为了进一步完善全球产业布局,DIOTEC于2007年在印度普纳建立了新的生产基地。这座工厂紧邻印度的“门户城市”孟买,为DIOTEC在印度市场的拓展提供了有力支持。印度工厂的投产,不仅加强了DIOTEC在全球市场的竞争力,也进一步巩固了其在亚洲市场的地位。

问答坊 | AI 解惑

电话机电路原理的详细解说ppt文件

电话机电路原理的详细解说ppt文件 ---------------------soso--------------------------------- 确认没有找到解压密码,请朋友们注意! 如果有解压密码的朋友,请与大家共享,谢谢!…

查看全部问答>

C8051初始化程序

本帖最后由 paulhyde 于 2014-9-15 03:22 编辑 C8051初始化程序以及各控制寄存器各位的定义说明  …

查看全部问答>

重金 寻求wince上(6410)播放rmvb视频的方案,期待与有成熟技术的公司合作!

重金 寻求wince上(6410)播放rmvb视频的方案,期待与有成熟技术的公司合作! 联系QQ:314629407 …

查看全部问答>

招聘程序员

招聘程序员: 具体要求见: www.chinadacs.cn …

查看全部问答>

有关PIC12F675 的PWM

__CONFIG(INTIO & WDTDIS & PWRTDIS & BORDIS & UNPROTECT & MCLRDIS); 这是我的配置字 这时是否应该使用内部晶振 且频率是4MHZ? 我用的是TMR0的中断来产生PWM波 TMR0的预分频器的设置如下 PS0=0; ;PS1=0; ;PS2=0;//1: ...…

查看全部问答>

请问ST_ARM关于Lwip!

                                 你好,我的Lwip能够接收到数据,但是无法ARP回显,我用PC机ping的时候,能够收到PC的ping数据包,但是Lwip就是不回 ...…

查看全部问答>

STM8S的16位定时器输入捕捉和PWM输出的问题

                                 请问STM8S的16位定时器,能同时使用输入捕捉和PWM输出吗,会不会有冲突?因为以前用AVR的,对于同一个定时器来说, ...…

查看全部问答>

请教绝对值的准确用法

请教各位同仁:int变量取绝对值用fabsf,fabs,fabsl的哪一个,谢谢!…

查看全部问答>

【数控电源】数控电源UART

这次数控电源我的任务是UART,想了想,不用中断越简单起好。所以就用了直接发只要调那个SEND就行   #include<lm3sxxx.h> void send(unsigned char aaa);void uartinit(void);void jtagWait(void); int main(void){   unsign ...…

查看全部问答>