Страница 1 из 3
STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 08:23:01
Pink-Pank
Всем Добрый день! Начал освоение Cortex-ов, вот затык у меня произошел. Не могу прочитать идентификатор акселерометра (для начала), расположенный по адресу 0x0F. Пишу в Keil, информация по
акселерометру и
SPI (+читал Reference Manual по SPI). Посылка по SPI идет (проверял цифровиком), а вот приема обратного байта нет.. Возвращает 0xFF.. Думаю, может скорость общения между устройствами слишком большая? Но у меня делитель и так на максимуме.. Вот код. Подскажите, что не так?
Спойлер
Код: Выделить всё
#include "stm32f4xx.h"
#define AAFRL (*(uint32_t *) 0x40020020)
#define SPI1EN 12
#define CPHA (1<<0) // Phase
#define CPOL (1<<1) // Polarity
#define MSTR (1<<2) // Master
#define BR0 (1<<3) // BitRate
#define BR1 (1<<4) // BitRate
#define BR2 (1<<5) // BitRate
#define SPE (1<<6) // on/off
#define LSBFIRST (1<<7) // Poryadok peredachi (0 - MSBFIRST)
#define SSI (1<<8) // Soft NSS (1 - vibran)
#define SSM (1<<9) // Soft (1)/Hard (0) NSS
#define RXONLY (1<<10) // Only read, no write (2-wire mode)
#define DFF (1<<11) // 0 - 8bit, 1 - 16bit frame
#define CRCNEXT (1<<12) //
#define CRCEN (1<<13) //
#define BIDIOE (1<<14) // 1 - translate, 0 - read (for 2-ware mode)
#define BIDIMODE (1<<15) // mode 2-ware translate.
#define SSOE (1<<2) // Slave output enable
//Button PA0
//LEDs PD12-PD15
//SPI PA5-PA7 (A6 - in)
//Int & CS PE0, PE1, PE3 (E3 - out)
void Init_ports (void);
void SPI_init (void);
void Write_SPI (char, char);
char Read_SPI (char);
unsigned long delay=0, i=0;
int main (void)
{
char XXX=0;
Init_ports ();
SPI_init();
for (i=0; i<500; i++) {};
XXX = Read_SPI (0x0F);
if (XXX == 0x3b){
GPIOD->BSRRL = (1<<12) | (1<<13) | (1<<14) | (1<<15);}
while (1);
}
void Init_ports (void)
{
RCC->AHB1ENR |= 0x19;
GPIOE->MODER = 0x40;
GPIOE->OTYPER = 0;
GPIOE->OSPEEDR = 0xFFFFFFFF;
GPIOE->BSRRL = (1<<3);
GPIOA->MODER |= 0xA800;
GPIOA->MODER &= ~0x5400;
GPIOA->OTYPER &= ~(0xA0);
GPIOA->OSPEEDR |= 0xCC00;
//GPIOA->AFR |= 0x55500000;
AAFRL |= 0x55500000;
GPIOD->MODER = 0x55000000;
GPIOD->OTYPER = 0;
GPIOD->OSPEEDR = 0xFFFFFFFF;
}
void SPI_init (void)
{
RCC->APB2ENR |= 1<<SPI1EN;
SPI1->CR1 = 0;
SPI1->CR1 |= BR0 | BR1 | BR2;
SPI1->CR1 |= CPOL;
SPI1->CR1 |= SSI | SSM;
//SPI1->CR2 = SSOE;
SPI1->CR2 = 0;
SPI1->CR1 |= SPE | MSTR;
}
void Write_SPI (char addres, char znachenie)
{
GPIOE->BSRRH = (1<<3);
addres &= 0x3F;
while (!(SPI1->SR & (1<<1)));
SPI1->DR = addres;
while (!(SPI1->SR & (1<<1)));
SPI1->DR = znachenie;
while (!(SPI1->SR & (1<<1)));
GPIOE->BSRRL = (1<<3);
}
char Read_SPI (char addres)
{
GPIOE->BSRRH = (1<<3);
addres |= 0x80;
while (!(SPI1->SR & (1<<1)));
SPI1->DR = addres;
while (!(SPI1->SR & (1<<1)));
SPI1->DR = 0x00;
while (!(SPI1->SR & (1<<1)));
GPIOE->BSRRL = (1<<3);
return SPI1->DR;
}
P.S. Сильно за код не ругайте, пытаюсь разобраться на уровне регистров, а не на уровне библиотеки. (хочется сначала понять, как работает, а уж потом верить библиотеке.)
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 09:29:11
ua1arn
Для начала - BSRRH ни разу не для чтения регистр... Шерсть встала дыбом, дальше смотреть не стал.
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 09:43:03
Pink-Pank
О, спасиб! Этот момент я прозевал. Тогда получается, что я не выбираю микросхему акселерометра. Ща подправлю - посмотрю, что будет.
Подправил, все равно акселерометр не запускается. Возвращает 0xFF
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 10:31:14
ua1arn
После первой отправки байта по SPI Вам тоже вернулся байт, который лежит себе в FIFO и ждёт пока считают... Считайте, отбросьте.
Пример SPI без библиотеки SPL вот тут -
http://188.134.5.254/browser/hfreceiver ... re.c#L3009.
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 10:47:56
Pink-Pank
А разве при выставлении адреса акселерометр что-то должен отправлять? Ввел переменную temp, считал, не помогло. Результат прежний.
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 12:05:58
ua1arn
- Выдали в порт сигнал на опускание CS. Выполнили __DSB();
Записали в DR адрес. Дождались SPI_SR_RXNE - считали DR - проигнорировали.
Записали в DR 0xff. Дождались SPI_SR_RXNE - считали DR - это ответ.
Сняли CS. Выполнили __DSB() - чтобы в следующий раз не "налететь". Вы в мой код заглядывали? Там это всё написано...
ps: не надо заводить переменных. Достаточно написать
Код: Выделить всё
(void) SPI1->DR; /* clear SPI_SR_RXNE in status register */
Да, к стати - какой SPI MODE требует акселерометр? Пробовали "ногодрыгом" работать с ним?
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 12:15:03
Pink-Pank
А вот здесь немного поподробнее, что таке __DSB()? Я так понял, это макрос какой-то ассемблерной команды? какой, что делает?
Вот выдержка настроек SPI для акселерометра с сайта:
Спойлер
Код: Выделить всё
//Заполняем структуру с параметрами SPI модуля
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //полный дуплекс
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // передаем по 8 бит
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // Полярность и
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // фаза тактового сигнала
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // Управлять состоянием сигнала NSS программно
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; // Предделитель SCK
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // Первым отправляется старший бит
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // Режим - мастер
SPI_Init(SPI1, &SPI_InitStructure); //Настраиваем SPI1
SPI_Cmd(SPI1, ENABLE); // Включаем модуль SPI1....
// Поскольку сигнал NSS контролируется программно, установим его в единицу
// Если сбросить его в ноль, то наш SPI модуль подумает, что
// у нас мультимастерная топология и его лишили полномочий мастера.
SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set);
__DSB(); не помогло.....
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 12:33:45
ua1arn
что таке __DSB()? Я так понял, это макрос какой-то ассемблерной команды? какой, что делает?
Да, ассемблерная команда, ВНЕЗАПНО DSB.
Следующая за ней команда выполнится после завершения вех отложенных записей. На STM32F4xx стало актуально, без этого выход у Вас переведётся в "0" где-то в середине передачи ьайта по SPI - даже на скоростях около 4-9 МГц я нарывался на это.
__DSB(); не помогло.....
Я ещё несколько советов дал... Помогло? Код в новой редакции сюда...
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 12:37:19
Pink-Pank
Спойлер
Код: Выделить всё
#include "stm32f4xx.h"
#define AAFRL (*(uint32_t *) 0x40020020)
#define SPI1EN 12
#define CPHA (1<<0) // Phase
#define CPOL (1<<1) // Polarity
#define MSTR (1<<2) // Master
#define BR0 (1<<3) // BitRate
#define BR1 (1<<4) // BitRate
#define BR2 (1<<5) // BitRate
#define SPE (1<<6) // on/off
#define LSBFIRST (1<<7) // Poryadok peredachi (0 - MSBFIRST)
#define SSI (1<<8) // Soft NSS (1 - vibran)
#define SSM (1<<9) // Soft (1)/Hard (0) NSS
#define RXONLY (1<<10) // Only read, no write (2-wire mode)
#define DFF (1<<11) // 0 - 8bit, 1 - 16bit frame
#define CRCNEXT (1<<12) //
#define CRCEN (1<<13) //
#define BIDIOE (1<<14) // 1 - translate, 0 - read (for 2-ware mode)
#define BIDIMODE (1<<15) // mode 2-ware translate.
#define SSOE (1<<2) // Slave output enable
//Button PA0
//LEDs PD12-PD15
//SPI PA5-PA7 (A6 - in)
//Int & CS PE0, PE1, PE3 (E3 - out)
void Init_ports (void);
void SPI_init (void);
void Write_SPI (char, char);
char Read_SPI (char);
unsigned long delay=0, i=0;
int main (void)
{
char XXX=0;
Init_ports ();
SPI_init();
for (i=0; i<300; i++) {};
XXX = Read_SPI (0x0F);
if (XXX == 0x3b){
GPIOD->BSRRL = (1<<12) | (1<<13) | (1<<14) | (1<<15);} \\ ON_LEDs
while (1);
}
void Init_ports (void)
{
RCC->AHB1ENR |= 0x19;
GPIOE->MODER = 0x40;
GPIOE->OTYPER = 0;
GPIOE->OSPEEDR = 0xFFFFFFFF;
GPIOE->BSRRL = (1<<3); \\ 3-d bit
GPIOA->MODER |= 0xA800;
GPIOA->MODER &= ~0x5400;
GPIOA->OTYPER &= ~(0xA0);
GPIOA->OSPEEDR |= 0xCC00;
//GPIOA->AFR |= 0x55500000;
AAFRL |= 0x55500000;
GPIOD->MODER = 0x55000000;
GPIOD->OTYPER = 0;
GPIOD->OSPEEDR = 0xFFFFFFFF;
}
void SPI_init (void)
{
RCC->APB2ENR |= 1<<SPI1EN;
SPI1->CR1 = 0;
SPI1->CR1 |= BR0 | BR1 | BR2;
SPI1->CR1 |= CPOL;
SPI1->CR1 |= SSI | SSM;
//SPI1->CR2 = SSOE;
SPI1->CR2 = 0;
SPI1->CR1 |= SPE | MSTR;
}
void Write_SPI (char addres, char znachenie)
{
GPIOE->BSRRH = (1<<3); \\ 3-d bit
__DSB();
addres &= 0x3F;
while (!(SPI1->SR & (1<<1))); \\ bit TXE
SPI1->DR = addres;
while (!(SPI1->SR & (1<<1))); \\ bit TXE
SPI1->DR = znachenie;
while (!(SPI1->SR & (1<<1))); \\ bit TXE
GPIOE->BSRRL = (1<<3); \\ 3-d bit
__DSB();
}
char Read_SPI (char addres)
{
GPIOE->BSRRH = (1<<3); \\ 3-d bit
__DSB();
addres |= 0x80;
while (!(SPI1->SR & (1<<1))); \\ bit TXE
SPI1->DR = addres;
while (!(SPI1->SR & (1<<1))); \\ bit TXE
while (!(SPI1->SR & (1<<0))); \\ bit RXNE
(void) SPI1->DR;
SPI1->DR = 0x00;
while (!(SPI1->SR & (1<<1))); \\ bit TXE
while (!(SPI1->SR & (1<<0))); \\ bit RXNE
GPIOE->BSRRL = (1<<3); \\ 3-d bit
__DSB();
return SPI1->DR;
}
Ногодрыг пока не трогал
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 12:48:37
ua1arn
Код "слепой", можете применять уже готовые макросы типа RCC_APB2ENR_SPI1EN - вместо комбинаций 1 и числа сдвигов? Очень тяжело понять что-либо.
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 12:59:45
Pink-Pank
А тогда мне не понятно будет. ) Я еще не привык к этим макросам. SPI тактируется, посылки идут. Проверено осциллом. А вот обратного ответа нет. Добавил комменты в код. А как в keil русскими буквами писать? и как числа в двоичном виде записывать?
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 13:02:55
ua1arn
Не надо в двоичном... хотя и можно. Придется считать позиции вручную - та ещё задача... Привыкните к макросам - не только Вам понятно будет.
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 16:36:14
Pink-Pank
Ну, кто-нибудь еще, поглядите, пожалуйста! А то я сам никак не найду, где косяк...

Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 18:02:34
dosikus
ua1arn писал(а):
Да, ассемблерная команда, ВНЕЗАПНО DSB.
Следующая за ней команда выполнится после завершения вех отложенных записей. На STM32F4xx стало актуально, без этого выход у Вас переведётся в "0" где-то в середине передачи ьайта по SPI - даже на скоростях около 4-9 МГц я нарывался на это.
Показательные танцы с бубном ?
Не пробовал даташит читать - на тему когда при каких событиях ставятся флаги в SPI ?
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 18:50:48
eess9
Сам недавно разбирался с этим акселерометром. LIS302DL_SPI1_INIT() инициализация этого дела, LIS302DL_READ_AXES_EVERY_SECOND() читает все 3 оси и если дефайн WRITE_TO_UART3 присутствует, то плюхает это дело в 3-й уарт. Но с SPI все таки разберитесь, т.к. дальше все равно вылезет проблема.
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 20:09:59
Pink-Pank
Это у Вас в Кокосе код? Я посмотрел, у мня тоже самое, только в регистры сам пишу, но не работает.. (( У Вас, кстати, ошибка. Операция WRITE должна устанавливать старший бит в 0, а READ - в 1. Вы же и там и там пишете | READ или | WRITE. Для WRITE нужно что-то типа & (~READ)) тогда будет сбрасывать старший бит.
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Пн июн 23, 2014 20:14:52
ua1arn
Код: Выделить всё
Не пробовал даташит читать - на тему когда при каких событиях ставятся флаги в SPI ?
Попробуйте на досуге программный ("ногодрыгательный") I2C на 429-м организовать... А насчет флагов в SPI - SPI давно инициализирован, чего ждать предлагаете в случае аппаратного SPI и ручного управления выводами порта?
У меня включена максимальная оптимизация по скорости в GCC (не ради ногодрыга, просто как DSP работает - так что вводу-выводу достаётся тоже оптимизации), когда всё что можно инлайнится благодаря lto, при использовании ST SPL на это не наткнетесь...
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Вт июн 24, 2014 07:15:43
dosikus
ua1arn писал(а):
Попробуйте на досуге программный ("ногодрыгательный") I2C на 429-м организовать...
И зачем? В новой периферии адекватный I2C, позволяет даже автоматические блочные запись/чтение....
ua1arn писал(а):
А насчет флагов в SPI - SPI давно инициализирован, чего ждать предлагаете в случае аппаратного SPI и ручного управления выводами порта?
Я не вижу твой код, но если ты как и TC проверяешь только TXE или BSY -
при однобайтных посылках , то оно так и будет .
Советую
внимательно изучить тайминги в даташите ...
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Вт июн 24, 2014 07:20:58
Pink-Pank
Может, кто-то по моему вопросу что-то скажет?..
Re: STMF4Discovery, SPI и акселерометр.
Добавлено: Вт июн 24, 2014 07:58:27
dosikus
Надо видеть твои посылки на ЛА , и MOSI и MISO и CS одновременно .
Как увидишь - все поймешь сам .
Разбираться с "неработой" интерфейсов без ЛА тот еще геморрой ...
А так - каждую проверку :
Код: Выделить всё
while (!(SPI1->SR & (1<<1))); или while (!(SPI1->SR &SPI_SR_TXE ));
Меняем на :
Код: Выделить всё
while(!(SPI1->SR & SPI_SR_RXNE)){}
(void) SPI1->DR;
Повторюсь - это
при однобайтовых посылках ...