реклама на сайте
подробности

 
 
> STM32F103 и компас HMC6352, проблема коммуникации
D1mcon
сообщение Oct 13 2010, 16:13
Сообщение #1





Группа: Новичок
Сообщений: 6
Регистрация: 2-08-10
Пользователь №: 58 729



Всем привет! Работаю с МК STM32F103 и компасом HMC6352 по I2C. Но ни как не могу прочитать данные о курсе, всегда компас возвращает значение 0х42. В чем причина, понять не могу. Если кто работал с этим компасом, прошу помочь в решении проблемы.
Код программы
Код
#include "stm32f10x.h"
#include "stm32f10x_i2c.h"


GPIO_InitTypeDef         GPIO_InitStructure;
USART_InitTypeDef         USART_InitStructure;
I2C_InitTypeDef            I2C_InitStructure;
FlagStatus Status = SET;    

#define I2C1_SLAVE_ADDRESS7   0x42
#define HMC6352GetData          0x41
#define BufferSize             4
#define ClockSpeed             100000
typedef enum { FAILED = 0, PASSED = !FAILED} TestStatus;

int angle = 0;
void Delay(unsigned long ms)// delay 1 ms per count @ Crystal 8.0 MHz and PLL9x or SYSCLK = 72 MHz
{
    volatile unsigned long i,j;
    for (i = 0; i < ms; i++ )
    for (j = 0; j < 5525; j++ );
}

int HMC6352GetHeading( void)
{
   unsigned char data_l = 0, data_m = 0;
  

       /* Send I2C1 START condition */
      I2C_GenerateSTART(I2C1, ENABLE);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

    I2C_Send7bitAddress(I2C1, 0x42, I2C_Direction_Transmitter);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ));

   I2C_SendData(I2C1,0x41);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ));

   Delay(60);

   I2C_GenerateSTART(I2C1, ENABLE);
   while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

   I2C_Send7bitAddress(I2C1, 0x43, I2C_Direction_Transmitter);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ));

   data_l = I2C_ReceiveData(I2C1);         // read LSB data byte
   data_m = I2C_ReceiveData(I2C1);         // read MSB data byte
   I2C_AcknowledgeConfig(I2C1, DISABLE);
                    
   I2C_GenerateSTOP(I2C1, ENABLE);      // send STOP condition
   return ( (data_m << 8) + data_l);   // return 16 bits data
}

void main()
{    

    SystemInit();
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA  | RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
      /* I2C1 Periph clock enable */
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    /* 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_AF_OD;
      GPIO_Init(GPIOB, &GPIO_InitStructure);

    /* 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;
      I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
      I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;
      I2C_Init(I2C1, &I2C_InitStructure);

    /* Enable I2C1 */
      I2C_Cmd(I2C1, ENABLE);

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_9 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
      GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_9;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
      GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
      GPIO_Init(GPIOA, &GPIO_InitStructure);


    
    USART_InitStructure.USART_BaudRate = 9600;
      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 configuration */
      USART_Init(USART1, &USART_InitStructure);
    
      /* Enable USART */
      USART_Cmd(USART1, ENABLE);
    angle = HMC6352GetHeading();
    
    while(1)
    {
        
            angle = HMC6352GetHeading();
        USART_SendData(USART1, (uint8_t) angle);
    

    }
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
KKV2003
сообщение Oct 21 2010, 03:25
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 30
Регистрация: 11-02-08
Пользователь №: 34 931



Вчера бился с другим девайсом через I2C ( почти, называется по другому ). В качестве контроллера взял Мегу8 ( что под рукой оказалось ). Подпрограммы взял в Инете, немного переделал. Не работало нормально. Достаточно долго бился и вот что понял.

В первоисточнике кода было написано, что после выдачи цикла записи адреса регистра для чтения ( 2-хфазный цикл записи ) достаточно выдать новый сигнал "Старт" на шину и дальше уже выдать 2-хфазный цикл чтения ( с единичным битом чтения/записи в идентификаторе ).

Так вот мой девайс такого делать не захотел - реагировал на новый идентификатор как на байт данных для записи. Пришлось вставлять "Стоп" перед "Стартом" - тогда все поехало.

То есть чтение происходило так:
1) Старт шины
2) Идентификатор четный ( на запись )
3) Адрес регистра для чтения
4) Стоп шины
5) Старт шины
6) Идентификатор нечетный ( на чтение )
7) Циклы чтения ( последний без квитанции от Мастера, остальные - без квитанции )
8) Стоп шины

Вот так у меня заработало.
Go to the top of the page
 
+Quote Post
Serj78
сообщение Oct 21 2010, 09:30
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 966
Регистрация: 27-05-06
Из: СПб
Пользователь №: 17 499



Цитата(KKV2003 @ Oct 21 2010, 07:25) *
То есть чтение происходило так:
1) Старт шины
2) Идентификатор четный ( на запись )
3) Адрес регистра для чтения
4) Стоп шины
5) Старт шины
6) Идентификатор нечетный ( на чтение )
7) Циклы чтения ( последний без квитанции от Мастера, остальные - без квитанции )
8) Стоп шины

Вот так у меня заработало.


Такой порядок чтения по запросу прямо указан в даташите на HMC6352 smile.gif

С этим компасом натолкнулся на одну проблему- на нескольких устройствах через 2..3 года слетает регистр режима из eeprom. Почему- не известно. По использованию - есть команды только на чтение, других устройств на шине нет.. Вылечил тем, что по старту устройства сначала записываем нужный режим работы.
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 13:12
Рейтинг@Mail.ru


Страница сгенерированна за 0.01421 секунд с 7
ELECTRONIX ©2004-2016