roboforum.ru

Технический форум по робототехнике.

STM32F103 и компас HMC6352

STM32F103 и компас HMC6352

D1mcon » 13 окт 2010, 19:57

Всем привет! Работаю с МК 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);
   

   }
Последний раз редактировалось Vooon 14 окт 2010, 12:34, всего редактировалось 1 раз.
Причина: [code=cpp]!

Re: STM32F103 и компас HMC6352

galex1981 » 18 окт 2010, 02:50

Может быть с адресами путаница?

Re: STM32F103 и компас HMC6352

D1mcon » 18 окт 2010, 07:46

Вроде нет, у него есть адрес по умолчанию, его я и использую, на I2C кроме компаса никого более нет.

Re: STM32F103 и компас HMC6352

D1mcon » 07 фев 2011, 23:31

Продолжаем разговор :) . Компас так и не заработал :( Причина - не получаю 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?
Вложения
hmc.jpg
hmc.jpg (46.82 КиБ) Просмотров: 7611

Re: STM32F103 и компас HMC6352

AlexandrY » 08 фев 2011, 00:15

Осцил плохой. Не показывает короткие звоны (100 нс и меньше) на фронтах клока. Небось разводка скверная, а?
Плюс звоны надо смотреть непосредственно на ногах чипа который не отвечает. От звонов помогают последовательные резисторы.

Re: STM32F103 и компас HMC6352

avr123.nm.ru » 08 фев 2011, 00:47

Сделайте скриншот картинки этого обмена из даташита для сравнения.

На последнем синим импульсе желтый должен был быть притянут на "0" компасом ?

А нога настраивается на вход чтобы позволить ему притянуть ? Можно поставить резистор 1 кОм между микрухами и посмотреть появится ли АСК ?

Re: STM32F103 и компас HMC6352

D1mcon » 08 фев 2011, 19:41

avr123.nm.ru писал(а):
На последнем синим импульсе желтый должен был быть притянут на "0" компасом ?

А нога настраивается на вход чтобы позволить ему притянуть ? Можно поставить резистор 1 кОм между микрухами и посмотреть появится ли АСК ?


Да, на последнем импульсе желтый должен был быть притянут на "0" компасом.
У компаса ноги никак не настраиваются.
Про резисторы не совсем понял - поставить на SCL и SDA,т.е. через резисторы подключить к МК?

Вот картинка из ДШ
SCL SDA - то что действительно должно происходить на I2C
M_SDA S_SDA - то что выдает мастер и ведомый соответственно

Добавлено спустя 1 час 3 минуты 18 секунд:
В общем резисторы не помогли, ставил и на клоки и на данные и только на данные :(
Разводка проста - отладочная плата и на 4-ех жильном шлейфе к ней подключен компас.
Вложения
hmc6352.JPG

Re: STM32F103 и компас HMC6352

AlexandrY » 08 фев 2011, 21:28

Ну тогда точно виноваты провода (либо контакты ;))
Можно пытаться на стороне компаса подвесить между SCL и землей конденсатор на 100...10 пик.
Если SDA и SCK в шлейфе идут рядом, то положить между ними проводник GND. Проверить фильтрацию питания на самом компасе в момент обмена по I2C. Шлейф укоротить до 1 см. Никаких других левых подсоединений к линиям SDA и SCL не должно быть.

Re: STM32F103 и компас HMC6352

D1mcon » 14 фев 2011, 22:55

Всем спасибо, причина была банальна - на демоплате была порвана дорожка клоков :Yahoo!:


Rambler\'s Top100 Mail.ru counter