|
STM32F103 и компас HMC6352, проблема коммуникации |
|
|
|
Oct 13 2010, 16:13
|
Группа: Новичок
Сообщений: 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);
}
|
|
|
|
|
 |
Ответов
(1 - 7)
|
Oct 19 2010, 14:37
|

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

|
Компас возвращает число от 0 до 3600 ( курс в десятых долях градуса.)
Вы выводите одно число (младшие 8 бит? ) что не совсем корректно. выводите два байта или курс, деленный на 20, так понятнее будет. Библиотеки I2c стандартные? Советую ими не пользоваться- в стандартных очень много фирменных индийских глюков.
Судя по коду, вы работаете в запросном режиме. Прочитайте для начала не курс, а хотя бы режим работы, смените его и снова прочитайте (через снятие питания) убедитесь что ваш ввод/ вывод правильно работает.
Посмотрите также (прочитайте данные из регистра), установлен ли periodic set/reset., иначе пластины сенсора не перемагничиваются и результат будет не верным (максимальным).
Надо обязательно выдавать подтверждение чтения первого байта (ASK), иначе второй не выведется (там будет FF, линия SDA отпустится) Также возьмите осциллограф и внимательно посмотрите на поведение линий после запроса байта 0х43..
|
|
|
|
|
Oct 20 2010, 06:06
|
Группа: Новичок
Сообщений: 6
Регистрация: 2-08-10
Пользователь №: 58 729

|
Спасибо, буду разбираться.
|
|
|
|
|
Oct 21 2010, 03:25
|
Участник

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

|
Вчера бился с другим девайсом через I2C ( почти, называется по другому ). В качестве контроллера взял Мегу8 ( что под рукой оказалось ). Подпрограммы взял в Инете, немного переделал. Не работало нормально. Достаточно долго бился и вот что понял.
В первоисточнике кода было написано, что после выдачи цикла записи адреса регистра для чтения ( 2-хфазный цикл записи ) достаточно выдать новый сигнал "Старт" на шину и дальше уже выдать 2-хфазный цикл чтения ( с единичным битом чтения/записи в идентификаторе ).
Так вот мой девайс такого делать не захотел - реагировал на новый идентификатор как на байт данных для записи. Пришлось вставлять "Стоп" перед "Стартом" - тогда все поехало.
То есть чтение происходило так: 1) Старт шины 2) Идентификатор четный ( на запись ) 3) Адрес регистра для чтения 4) Стоп шины 5) Старт шины 6) Идентификатор нечетный ( на чтение ) 7) Циклы чтения ( последний без квитанции от Мастера, остальные - без квитанции ) 8) Стоп шины
Вот так у меня заработало.
|
|
|
|
|
Feb 7 2011, 19:48
|
Группа: Новичок
Сообщений: 6
Регистрация: 2-08-10
Пользователь №: 58 729

|
Продолжаем разговор  . Компас после нескольких месяцев не заработал  Причина - не получаю 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?
Эскизы прикрепленных изображений
|
|
|
|
|
Feb 14 2011, 19:48
|
Группа: Новичок
Сообщений: 6
Регистрация: 2-08-10
Пользователь №: 58 729

|
Вобщем проблема решена - нашел на демоплате перебитую дорожку на клоки.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|