STMF4Discovery, SPI и акселерометр.

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение 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. Сильно за код не ругайте, пытаюсь разобраться на уровне регистров, а не на уровне библиотеки. (хочется сначала понять, как работает, а уж потом верить библиотеке.)
Последний раз редактировалось Pink-Pank Пн июн 23, 2014 09:49:12, всего редактировалось 1 раз.
Fucking static initialization order fiasco
Контактная информация:
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 81
Зарегистрирован: Вт май 08, 2012 23:15:45
Откуда: Санкт - Петербург

Сообщение ua1arn »

Для начала - BSRRH ни разу не для чтения регистр... Шерсть встала дыбом, дальше смотреть не стал.
Реклама
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

О, спасиб! Этот момент я прозевал. Тогда получается, что я не выбираю микросхему акселерометра. Ща подправлю - посмотрю, что будет.
Подправил, все равно акселерометр не запускается. Возвращает 0xFF
Fucking static initialization order fiasco
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 81
Зарегистрирован: Вт май 08, 2012 23:15:45
Откуда: Санкт - Петербург

Сообщение ua1arn »

После первой отправки байта по SPI Вам тоже вернулся байт, который лежит себе в FIFO и ждёт пока считают... Считайте, отбросьте.

Пример SPI без библиотеки SPL вот тут - http://188.134.5.254/browser/hfreceiver ... re.c#L3009.
Реклама
Эиком - электронные компоненты и радиодетали
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

А разве при выставлении адреса акселерометр что-то должен отправлять? Ввел переменную temp, считал, не помогло. Результат прежний.
Fucking static initialization order fiasco
Контактная информация:
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 81
Зарегистрирован: Вт май 08, 2012 23:15:45
Откуда: Санкт - Петербург

Сообщение 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 требует акселерометр? Пробовали "ногодрыгом" работать с ним?
Реклама
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение 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(); не помогло.....
Fucking static initialization order fiasco
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 81
Зарегистрирован: Вт май 08, 2012 23:15:45
Откуда: Санкт - Петербург

Сообщение ua1arn »

что таке __DSB()? Я так понял, это макрос какой-то ассемблерной команды? какой, что делает?
Да, ассемблерная команда, ВНЕЗАПНО DSB.
Следующая за ней команда выполнится после завершения вех отложенных записей. На STM32F4xx стало актуально, без этого выход у Вас переведётся в "0" где-то в середине передачи ьайта по SPI - даже на скоростях около 4-9 МГц я нарывался на это.
__DSB(); не помогло.....
Я ещё несколько советов дал... Помогло? Код в новой редакции сюда...
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение 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;
}
Ногодрыг пока не трогал
Последний раз редактировалось Pink-Pank Пн июн 23, 2014 12:58:27, всего редактировалось 2 раза.
Fucking static initialization order fiasco
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 81
Зарегистрирован: Вт май 08, 2012 23:15:45
Откуда: Санкт - Петербург

Сообщение ua1arn »

Код "слепой", можете применять уже готовые макросы типа RCC_APB2ENR_SPI1EN - вместо комбинаций 1 и числа сдвигов? Очень тяжело понять что-либо.
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

А тогда мне не понятно будет. ) Я еще не привык к этим макросам. SPI тактируется, посылки идут. Проверено осциллом. А вот обратного ответа нет. Добавил комменты в код. А как в keil русскими буквами писать? и как числа в двоичном виде записывать?
Fucking static initialization order fiasco
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 81
Зарегистрирован: Вт май 08, 2012 23:15:45
Откуда: Санкт - Петербург

Сообщение ua1arn »

Не надо в двоичном... хотя и можно. Придется считать позиции вручную - та ещё задача... Привыкните к макросам - не только Вам понятно будет.
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Ну, кто-нибудь еще, поглядите, пожалуйста! А то я сам никак не найду, где косяк... :cry:
Fucking static initialization order fiasco
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Сообщение dosikus »

ua1arn писал(а): Да, ассемблерная команда, ВНЕЗАПНО DSB.
Следующая за ней команда выполнится после завершения вех отложенных записей. На STM32F4xx стало актуально, без этого выход у Вас переведётся в "0" где-то в середине передачи ьайта по SPI - даже на скоростях около 4-9 МГц я нарывался на это.
Показательные танцы с бубном ? :)))
Не пробовал даташит читать - на тему когда при каких событиях ставятся флаги в SPI ?
Вымогатель припоя
Аватара пользователя
Сообщения: 672
Зарегистрирован: Ср фев 29, 2012 01:58:32
Откуда: Харьков, Украина

Сообщение eess9 »

Сам недавно разбирался с этим акселерометром. LIS302DL_SPI1_INIT() инициализация этого дела, LIS302DL_READ_AXES_EVERY_SECOND() читает все 3 оси и если дефайн WRITE_TO_UART3 присутствует, то плюхает это дело в 3-й уарт. Но с SPI все таки разберитесь, т.к. дальше все равно вылезет проблема.
Вложения
LIS302DL_SPI1.h
(1.34 КБ) 491 скачивание
LIS302DL_SPI1.c
(3.99 КБ) 556 скачиваний
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Это у Вас в Кокосе код? Я посмотрел, у мня тоже самое, только в регистры сам пишу, но не работает.. (( У Вас, кстати, ошибка. Операция WRITE должна устанавливать старший бит в 0, а READ - в 1. Вы же и там и там пишете | READ или | WRITE. Для WRITE нужно что-то типа & (~READ)) тогда будет сбрасывать старший бит.
Последний раз редактировалось Pink-Pank Пн июн 23, 2014 20:21:32, всего редактировалось 2 раза.
Fucking static initialization order fiasco
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 81
Зарегистрирован: Вт май 08, 2012 23:15:45
Откуда: Санкт - Петербург

Сообщение ua1arn »

Код: Выделить всё

Не пробовал даташит читать - на тему когда при каких событиях ставятся флаги в SPI ?
Попробуйте на досуге программный ("ногодрыгательный") I2C на 429-м организовать... А насчет флагов в SPI - SPI давно инициализирован, чего ждать предлагаете в случае аппаратного SPI и ручного управления выводами порта?
У меня включена максимальная оптимизация по скорости в GCC (не ради ногодрыга, просто как DSP работает - так что вводу-выводу достаётся тоже оптимизации), когда всё что можно инлайнится благодаря lto, при использовании ST SPL на это не наткнетесь...
Друг Кота
Аватара пользователя
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Сообщение dosikus »

ua1arn писал(а): Попробуйте на досуге программный ("ногодрыгательный") I2C на 429-м организовать...
И зачем? В новой периферии адекватный I2C, позволяет даже автоматические блочные запись/чтение....

ua1arn писал(а): А насчет флагов в SPI - SPI давно инициализирован, чего ждать предлагаете в случае аппаратного SPI и ручного управления выводами порта?
Я не вижу твой код, но если ты как и TC проверяешь только TXE или BSY - при однобайтных посылках , то оно так и будет .
Советую внимательно изучить тайминги в даташите ...
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Может, кто-то по моему вопросу что-то скажет?..
Fucking static initialization order fiasco
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Сообщение dosikus »

Надо видеть твои посылки на ЛА , и MOSI и MISO и CS одновременно .
Как увидишь - все поймешь сам . :)))

Разбираться с "неработой" интерфейсов без ЛА тот еще геморрой ...

А так - каждую проверку :

Код: Выделить всё

while (!(SPI1->SR & (1<<1)));  или while (!(SPI1->SR &SPI_SR_TXE ));
Меняем на :

Код: Выделить всё

while(!(SPI1->SR & SPI_SR_RXNE)){}
(void) SPI1->DR;

Повторюсь - это при однобайтовых посылках ...
Ответить

Вернуться в «ARM»