ele-madman 发表于 2013-9-10 15:26:24

HMC5883L 模拟I2C程序STM32

不多说,直接上程序

julian 发表于 2013-9-12 18:16:21

专门为新手准备的。。。

radar_12345 发表于 2014-3-31 22:16:34

楼主好人啊,我用STM8L模拟的,读出来的全是0xff, 感觉是I2C没搞定,参考下楼主的

afeionline 发表于 2014-4-1 21:30:57

radar_12345 发表于 2014-3-31 22:16
楼主好人啊,我用STM8L模拟的,读出来的全是0xff, 感觉是I2C没搞定,参考下楼主的 ...

如果读出来全F,检查一下你IO口模式设置是不是对的。
I2C的IO口需要设置为开漏输出,然后在线上加上拉电阻。

话说楼主为什么要用STM32模拟I2C呢?STM32不应该带硬件I2C控制器吗?

sun92845166 发表于 2014-6-11 19:33:31

#在这里快速回复这个模拟I2C的代码也是在本站下载的,原来是访问EEPROM的。我使用STM32来访问I2C接口的铁电存储器,FM24CL16,2K字节,比访问EEPROM要方便一点,所以简单修改了一下,比原来少很多。感谢ground网友提供的原始代码! FM24CL16的手册由于文件服务器问题,暂时传不上来。等阿莫弄好了再传吧。   代码就不打包了,直接贴上来了 ================================= I2C的引脚配置:/* Configure I2C1 pins: SCL and SDA */   GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6 | GPIO_Pin_7;   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;   GPIO_Init(GPIOB, &GPIO_InitStructure); ================================= /******************************************************************************* * File Name          : i2c_fram.h * Author             : MCD Application Team * Version            : V2.0.1 * Date               : 06/13/2008 * Description      : Header for i2c_ee.c module *******************************************************************************/ /* Define to prevent recursive inclusion ------------------------------------ */ #ifndef __I2C_FRAM_H #define __I2C_FRAM_H/* Includes ------------------------------------------------------------------*/ #include "stm32f10x_lib.h"/* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/   /* Exported macro ------------------------------------------------------------*/ /* Exported functions ------------------------------------------------------- */   bool I2C_FRAM_BufferWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite); bool I2C_FRAM_BufferRead(u8* pBuffer, u16 ReadAddr, u16 NumByteToRead);#endif /* __I2C_FRAM_H */================================= /******************************************************************************* * File Name          : i2c_fram.c * Author             : Appcat * Version            : V0.0.1 * Date               : 07/11/2009 * Description      : This file provides a set of functions needed to manage the *                      communication between I2C peripheral and I2C FM24CL16 FRAM. *******************************************************************************//* Includes ------------------------------------------------------------------*/ #include "i2c_fram.h"/* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ #define I2C_Speed            100000 #define I2C1_SLAVE_ADDRESS7    0xA0 #define I2C_PageSize         256#define SCL_H         GPIOB->BSRR = GPIO_Pin_6 #define SCL_L         GPIOB->BRR= GPIO_Pin_6      #define SDA_H         GPIOB->BSRR = GPIO_Pin_7 #define SDA_L         GPIOB->BRR= GPIO_Pin_7#define SCL_read      GPIOB->IDR& GPIO_Pin_6 #define SDA_read      GPIOB->IDR& GPIO_Pin_7   /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ vu8 FRAM_ADDRESS;/* Private function prototypes -----------------------------------------------*//**/ void I2C_delay(void) {            u8 i=150; //这里可以优化速度      ,经测试最低到5还能写入    while(i)   {       i--;   }}bool I2C_Start(void) {         SDA_H;         SCL_H;         I2C_delay();         if(!SDA_read)return FALSE;      //SDA线为低电平则总线忙,退出         SDA_L;         I2C_delay();         if(SDA_read) return FALSE;      //SDA线为高电平则总线出错,退出         SDA_L;         I2C_delay();         return TRUE; }void I2C_Stop(void) {         SCL_L;         I2C_delay();         SDA_L;         I2C_delay();         SCL_H;         I2C_delay();         SDA_H;         I2C_delay(); }void I2C_Ack(void) {               SCL_L;         I2C_delay();         SDA_L;         I2C_delay();         SCL_H;         I2C_delay();         SCL_L;         I2C_delay(); }void I2C_NoAck(void) {               SCL_L;         I2C_delay();         SDA_H;         I2C_delay();         SCL_H;         I2C_delay();         SCL_L;         I2C_delay(); }bool I2C_WaitAck(void)          //返回为:=1有ACK,=0无ACK {         SCL_L;         I2C_delay();         SDA_H;                                 I2C_delay();         SCL_H;         I2C_delay();         if(SDA_read)         {       SCL_L;       return FALSE;         }         SCL_L;         return TRUE; }void I2C_SendByte(u8 SendByte) //数据从高位到低位// {   u8 i=8;   while(i--)   {         SCL_L;         I2C_delay();       if(SendByte&0x80)         SDA_H;         else          SDA_L;            SendByte<<=1;         I2C_delay();               SCL_H;         I2C_delay();   }   SCL_L; }u8 I2C_ReceiveByte(void)//数据从高位到低位// {      u8 i=8;   u8 ReceiveByte=0;      SDA_H;                                     while(i--)   {       ReceiveByte<<=1;             SCL_L;       I2C_delay();         SCL_H;       I2C_delay();               if(SDA_read)       {         ReceiveByte|=0x01;       }   }   SCL_L;   return ReceiveByte; }bool I2C_FRAM_BufferWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite) {         u8 Addr = 0, count = 0;          Addr = WriteAddr / I2C_PageSize;          count = WriteAddr % I2C_PageSize;          Addr = Addr << 1;          Addr = Addr & 0x0F;            FRAM_ADDRESS = I2C1_SLAVE_ADDRESS7 | Addr;      if (!I2C_Start()) return FALSE;   I2C_SendByte(FRAM_ADDRESS);//设置器件地址+段地址      if (!I2C_WaitAck())         {               I2C_Stop();                  return FALSE;         }   I2C_SendByte(count);   //设置段内地址               I2C_WaitAck();                            while(NumByteToWrite--)         {         I2C_SendByte(* pBuffer);         I2C_WaitAck();       pBuffer++;         }         I2C_Stop();         //注意:因为这里要等待EEPROM写完,可以采用查询或延时方式(10ms)         //Systick_Delay_1ms(10);         return TRUE; }   //读出1串数据          bool I2C_FRAM_BufferRead(u8* pBuffer, u16 WriteAddr, u16 NumByteToRead) {                         u8 Addr = 0, count = 0;      Addr = WriteAddr / I2C_PageSize;          count = WriteAddr % I2C_PageSize;          Addr = Addr << 1;          Addr = Addr & 0x0F;            FRAM_ADDRESS = I2C1_SLAVE_ADDRESS7 | Addr;                  if (!I2C_Start()) return FALSE;      I2C_SendByte(FRAM_ADDRESS);//设置器件地址+段地址       if (!I2C_WaitAck())          {               I2C_Stop();                  return FALSE;         }      I2C_SendByte(count);   //设置低起始地址         I2C_WaitAck();   I2C_Start();   I2C_SendByte(FRAM_ADDRESS | 0x01);   I2C_WaitAck();   while(NumByteToRead)   {       *pBuffer = I2C_ReceiveByte();       if(NumByteToRead == 1)I2C_NoAck();       else I2C_Ack();      pBuffer++;       NumByteToRead--;   }   I2C_Stop();   return TRUE; }

技术平原 发表于 2014-6-25 16:28:21

楼主的角度算法程序有问题,0度和360度那里会不正常

TheBest 发表于 2015-6-15 16:59:38

楼主好人啊,言简意赅

destiny、 发表于 2015-8-28 12:36:01

楼主你好,你写过罗盘校准吗?我读出来的数据在0和360度附近的+-50度变化特别大,不连续,一下能跳好几十、、、、

沉默胜过白金 发表于 2016-1-16 20:29:12

LZ好人,下载下来试试。
页: [1]
查看完整版本: HMC5883L 模拟I2C程序STM32