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

 
 
> 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
Ответов (1 - 7)
Serj78
сообщение Oct 19 2010, 14:37
Сообщение #2


Знающий
****

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



Компас возвращает число от 0 до 3600 ( курс в десятых долях градуса.)

Вы выводите одно число (младшие 8 бит? ) что не совсем корректно. выводите два байта или курс, деленный на 20, так понятнее будет.
Библиотеки I2c стандартные? Советую ими не пользоваться- в стандартных очень много фирменных индийских глюков.

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

Посмотрите также (прочитайте данные из регистра), установлен ли periodic set/reset., иначе пластины сенсора не перемагничиваются и результат будет не верным (максимальным).

Надо обязательно выдавать подтверждение чтения первого байта (ASK), иначе второй не выведется (там будет FF, линия SDA отпустится)
Также возьмите осциллограф и внимательно посмотрите на поведение линий после запроса байта 0х43..
Go to the top of the page
 
+Quote Post
D1mcon
сообщение Oct 20 2010, 06:06
Сообщение #3





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



Спасибо, буду разбираться.
Go to the top of the page
 
+Quote Post
KKV2003
сообщение Oct 21 2010, 03:25
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 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
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 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
KKV2003
сообщение Oct 21 2010, 14:39
Сообщение #6


Участник
*

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



Хорошо вам... А в моем даташите такого не было. Так что помучился. laughing.gif
Go to the top of the page
 
+Quote Post
D1mcon
сообщение Feb 7 2011, 19:48
Сообщение #7





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



Продолжаем разговор sm.gif . Компас после нескольких месяцев не заработал sad.gif Причина - не получаю ACK после передачи адреса.
Привожу немного измененный код
Код
#include "stm32f10x.h"
#include "stm32f10x_i2c.h"



I2C_InitTypeDef            I2C_InitStructure;
FlagStatus Status = SET;    

#define ReadAddress                0x43
#define WriteAddress            0x42
#define BufferSize              4
#define GetHeading                0x41
#define ClockSpeed              100000

int I2C_address = 0;
bool exit = FALSE;
I2C_TypeDef* HMC6352_I2C;

void HMC6352Init(I2C_TypeDef* HMC6352_I2Cx)
{    
    GPIO_InitTypeDef         GPIO_InitStructure;
    I2C_InitTypeDef            I2C_InitStructure;
    
    HMC6352_I2C = HMC6352_I2Cx;
       I2C_Cmd(HMC6352_I2C, DISABLE);
       I2C_DeInit(HMC6352_I2C);
                                    
                                                      
    /* Configure I2C1 pins: SCL and SDA ----------------------------------------*/    
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);

      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 = 0x00;
      I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
      I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
      I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;
      
      I2C_Init(HMC6352_I2C, &I2C_InitStructure);
    I2C_Cmd(HMC6352_I2C, ENABLE);
      
        

}

int HMC6352GetHeading()
{
  
  __IO uint16_t RegValue = 0;
  
  I2C_AcknowledgeConfig(HMC6352_I2C, ENABLE);
  /*--------------------------------- Transmission Phase ------------------*/

  I2C_GenerateSTART(HMC6352_I2C, ENABLE);
  while (!I2C_CheckEvent(HMC6352_I2C, I2C_EVENT_MASTER_MODE_SELECT));  /*!< EV5 */

  I2C_Send7bitAddress(HMC6352_I2C, WriteAddress, I2C_Direction_Transmitter);
  while (!I2C_CheckEvent(HMC6352_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); /*!< EV6 */
  
  I2C_SendData(HMC6352_I2C, GetHeading);
  while (!I2C_CheckEvent(HMC6352_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /*!< EV8 */


  /*-------------------------------- Reception Phase --------------------------*/
  I2C_GenerateSTART(HMC6352_I2C, ENABLE);
  while (!I2C_CheckEvent(HMC6352_I2C, I2C_EVENT_MASTER_MODE_SELECT));  /*!< EV5 */

  I2C_Send7bitAddress(HMC6352_I2C, ReadAddress, I2C_Direction_Receiver);
  while (!I2C_CheckEvent(HMC6352_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));  /*!< EV6 */
  while (!I2C_CheckEvent(HMC6352_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED));  /*!< EV7 */

  RegValue = I2C_ReceiveData(HMC6352_I2C) << 8;
  I2C_AcknowledgeConfig(HMC6352_I2C, DISABLE);
  I2C_GenerateSTOP(HMC6352_I2C, ENABLE);

  while (I2C_GetFlagStatus(HMC6352_I2C, I2C_FLAG_RXNE) == RESET);
  RegValue |= I2C_ReceiveData(HMC6352_I2C);


  return (RegValue/10);
}


И сигналы SCL и SDA. По сигналам видно что нормально происходит старт I2c, посылка адреса, но на 9 клоке SDA = 1, компас не ответил :cry:
Частота настроена верно. Питание на компасе есть. Подтягивающие резисторы на SCL и SDA по 2КОм, при 10КОм, как в ДШ на компас, сильно заваливались фронты.
Подскажите, в чем может быть причина отсутствия ACK?

Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
D1mcon
сообщение Feb 14 2011, 19:48
Сообщение #8





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



Вобщем проблема решена - нашел на демоплате перебитую дорожку на клоки.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 11:45
Рейтинг@Mail.ru


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