Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.71/34: Рейтинг темы: голосов - 34, средняя оценка - 4.71
1 / 1 / 0
Регистрация: 17.07.2015
Сообщений: 27

Передача данных по SPI, между АЦП и микроконтроллером

20.03.2017, 05:33. Показов 7106. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день.
Понемногу разбираясь с микроконтроллерами, решил связать МК с АЦП посредством SPI. Но, как мне кажется, возникла проблема:
длинна выходного сообщения с АЦП - 32 бита: LTC2498 (стр. 16),
а максимальная длинна входного, у МК - 16:
STM32F051C8 (стр. 721).
Получается, я не могу получить на STM32F051C8 полной информации, поступающей с LTC2498? Максимум - какой-то обрывок, принудительно обрывая передачу данных с АЦП.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
20.03.2017, 05:33
Ответы с готовыми решениями:

Передача данных между МК по SPI
Добрый день, поставил задачу передавать число от мастера к слейву, слейв прибавляет 1 к этому числу и возвращает мастеру, мастер это число...

Работа с АЦП микроконтроллером PIC
movlw b'11111111' movwf TRISA movlw b'00000001' movwf TRISB clrf TRISD bcf STATUS, RP0 Если добавить код ...

Передача данных по SPI на расстояние
Здравствуйте. Почти уже доделал проект, где 2 МК (ATm16 и 8) общаются друг с другом по SPI, убив куча времени. И сейчас выяснилось, что эти...

21
Эксперт .NET
 Аватар для Rius
13114 / 7675 / 1674
Регистрация: 25.05.2015
Сообщений: 23,404
Записей в блоге: 14
20.03.2017, 06:10
Цитата Сообщение от Basitin Посмотреть сообщение
STM32F051C8 (стр. 721).
Там вообще-то про UART как бы, но это не важно.
Микроконтроллеры по своим интерфейсам связи не ограничены размерами регистров. Данные по мере приёма или передачи подкачиваются в/из памяти, постоянной или оперативной. Особенно для этого предназначен DMA.
1
 Аватар для Витальич
1280 / 1185 / 175
Регистрация: 02.12.2013
Сообщений: 4,883
20.03.2017, 08:00
Цитата Сообщение от Basitin Посмотреть сообщение
(стр. 16)
принять четыре байта, с программным управлением "CS"
1
1 / 1 / 0
Регистрация: 17.07.2015
Сообщений: 27
20.03.2017, 17:26  [ТС]
Мой косяк. Страница 765.
Спасибо за ответ. Мне казалось что при конфигурированнии SPI, я ограничиваю длину сообщений в 8 или 16 бит, как (приём) RX так и (передачу) TX.
0
Эксперт .NET
 Аватар для Rius
13114 / 7675 / 1674
Регистрация: 25.05.2015
Сообщений: 23,404
Записей в блоге: 14
20.03.2017, 17:29
Нет, там указывается размер одной единицы данных, которыми управляет модуль. А не максимальный размер посылки, состоящей из множества этих данных.
1
1 / 1 / 0
Регистрация: 17.07.2015
Сообщений: 27
28.03.2017, 10:53  [ТС]
Извиняюсь за долгое отсутствие.
Как выдалось свободное время, продолжил дальше мучить STM.
Пытаюсь передать "настроечные" биты на АЦП LTC2498, но даже в регистр передачи DR ничего не заносится, он как был пустой, таким и остается.
При тактировании и настройке порта B и SPI руководствовался примерами из интернета и, само-собой, мануалом к МК.
Но, видимо, где-то допустил ошибку, которую у меня не получается найти.

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "stm32f0xx.h"
uint32_t n;
 
void initALL (void) 
{
    /* PORT B */
    
    RCC  ->AHBENR   |= (RCC_AHBENR_GPIOBEN);  //Тактирование порта В
    GPIOB->MODER      |=    GPIO_OSPEEDR_OSPEEDR12 | GPIO_OSPEEDR_OSPEEDR13 | GPIO_OSPEEDR_OSPEEDR14 | GPIO_OSPEEDR_OSPEEDR15; //Устанавливаем бит MODE0 для выводов порта (режим GPIO)
    GPIOB->OTYPER   &=  (~GPIO_OTYPER_OT_12)     & (~GPIO_OTYPER_OT_13)   & (~GPIO_OTYPER_OT_14)   & (~GPIO_OTYPER_OT_15); //Сбрасываем бит OT для выводов (режим Push-Pull) 
    GPIOB->OSPEEDR  |= GPIO_OSPEEDR_OSPEEDR12    | GPIO_OSPEEDR_OSPEEDR13 | GPIO_OSPEEDR_OSPEEDR14 | GPIO_OSPEEDR_OSPEEDR15;  //50Mhz 
    
    GPIOB->AFR[1]   |= (5<<28 | 5<<24 | 5<<20  | 5<<16); //PB15, PB14, P13, PB12 = AF5 
    
    /* SPI   */
    
                RCC->APB1ENR  |= RCC_APB1ENR_SPI2EN; //Тактирование модуля SPI2
        SPI2->CR1     |= SPI_CR1_BR; //Baud rate = Fpclk/256
        SPI2->CR1     |= SPI_CR1_CPOL | SPI_CR1_CPHA; //Полярность тактового сигнала
        SPI2->CR1     &= ~SPI_CR1_CPHA; //Фаза тактового сигнала
        SPI2->CR2     |= SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2;  //8 бит данных
        SPI2->CR1     &= ~SPI_CR1_LSBFIRST; //MSB передается первым
        SPI2->CR1     &= ~SPI_CR1_SSM; //Программный режим NSS
        SPI2->CR1     |= SPI_CR1_SSI;  //Аналогично состоянию, когда на входе NSS высокий уровень
        SPI2->CR2     |= SPI_CR2_SSOE; //Вывод NSS - выход управления slave select
        SPI2->CR1     |= SPI_CR1_MSTR; //Режим Master
        SPI2->CR1     |= SPI_CR1_SPE; //Включаем SPI2
    
    return;
}
 
void spi_exchange(uint32_t data)
{
    SPI2->DR =0x9780;  //Передаем на АЦП байты настройки
  while(!(SPI2->SR & SPI_SR_RXNE));//Ожидаем окончания приема данных модулем SPI2 (RXNE =1 - приемный буфер содержит данные)
    SPI2->DR = data; //Считываем данные из приемного буфера SPI2. При этой операции происходит очистка буфера и сброс флага RXNE
 
    return;
}
 
int main (void)
{
    initALL();
    while (1)
    {   
    spi_exchange(n);
    }
}
0
1 / 1 / 0
Регистрация: 17.07.2015
Сообщений: 27
30.03.2017, 08:16  [ТС]
Сделал инициализацию строго по даташиту. Не помогло.(
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include "stm32f0xx.h"
uint32_t n;
 
void initALL (void) 
{
    /* PORT B */
    
    RCC  ->AHBENR   |= (RCC_AHBENR_GPIOBEN);  //Тактирование порта В
    GPIOB->MODER      |=    GPIO_OSPEEDR_OSPEEDR12 | GPIO_OSPEEDR_OSPEEDR13 | GPIO_OSPEEDR_OSPEEDR14 | GPIO_OSPEEDR_OSPEEDR15; //Устанавливаем бит MODE0 для выводов порта (режим GPIO)
    GPIOB->OTYPER   &=  (~GPIO_OTYPER_OT_12)     & (~GPIO_OTYPER_OT_13)   & (~GPIO_OTYPER_OT_14)   & (~GPIO_OTYPER_OT_15); //Сбрасываем бит OT для выводов (режим Push-Pull) 
    GPIOB->OSPEEDR  |= GPIO_OSPEEDR_OSPEEDR12    | GPIO_OSPEEDR_OSPEEDR13 | GPIO_OSPEEDR_OSPEEDR14 | GPIO_OSPEEDR_OSPEEDR15;  //50Mhz 
    
    GPIOB->AFR[1]   |= (5<<28 | 5<<24 | 5<<20  | 5<<16); //PB15, PB14, P13, PB12 = AF5 
    
    /* SPI   */
    
    RCC->APB1ENR  |= RCC_APB1ENR_SPI2EN; //Тактирование модуля SPI2
        SPI2->CR1  = SPI_CR1_MSTR | SPI_CR1_BR       | SPI_CR1_BIDIMODE | SPI_CR1_SSM;
        SPI2->CR2  = SPI_CR2_SSOE | SPI_CR2_RXNEIE | SPI_CR2_TXDMAEN    | SPI_CR2_FRXTH | SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0; 
        SPI2->CR1 |= SPI_CR1_SPE;
    
    return;
}
 
void spi_exchange(uint32_t data)
{
    SPI2->DR = 0x9780;  //Передаем на АЦП байты настройки
  while(!(SPI2->SR & SPI_SR_RXNE));//Ожидаем окончания приема данных модулем SPI2 (RXNE =1 - приемный буфер содержит данные)
    SPI2->DR = data; //Считываем данные из приемного буфера SPI2. При этой операции происходит очистка буфера и сброс флага RXNE
 
    return;
}
 
int main (void)
{
    initALL();
    while (1)
    {   
    spi_exchange(n);
    }
}
0
1 / 1 / 0
Регистрация: 17.07.2015
Сообщений: 27
01.04.2017, 10:23  [ТС]
Воспользовался STM-овской библиотекой, для МК моей серии:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include "stm32f0xx.h"     
#include "stm32f0xx_rcc.h"
#include "stm32f0xx_gpio.h"
#include "stm32f0xx_spi.h"
 
#define CS_ON() GPIO_ResetBits(GPIOB, GPIO_Pin_12)
#define CS_OFF() GPIO_SetBits(GPIOB, GPIO_Pin_12)
 
uint16_t SPIdata=0;
 
void Allini(void)
{
    GPIO_InitTypeDef GPIO_spi;
    SPI_InitTypeDef SPI_ini;
    
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
    GPIO_spi.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_spi.GPIO_Mode = GPIO_Mode_AF; 
    GPIO_spi.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_spi.GPIO_OType = GPIO_OType_PP;
    GPIO_spi.GPIO_PuPd = GPIO_PuPd_NOPULL;
    
    GPIO_Init(GPIOB, &GPIO_spi);
    
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_1);
    
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
    GPIO_spi.GPIO_Pin = GPIO_Pin_12;
    GPIO_spi.GPIO_Mode = GPIO_Mode_OUT; 
    GPIO_spi.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_spi.GPIO_OType = GPIO_OType_PP;
    GPIO_spi.GPIO_PuPd = GPIO_PuPd_NOPULL;
    
    GPIO_Init(GPIOB, &GPIO_spi);
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
    SPI_ini.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_ini.SPI_Mode = SPI_Mode_Master;
    SPI_ini.SPI_DataSize = SPI_DataSize_16b;
    SPI_ini.SPI_CPOL = SPI_CPOL_High; 
    SPI_ini.SPI_CPHA = SPI_CPHA_2Edge;
    SPI_ini.SPI_NSS = SPI_NSS_Soft;
    SPI_ini.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
    SPI_ini.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_ini.SPI_CRCPolynomial = 7;
    
    SPI_Init(SPI2, &SPI_ini);
    
    SPI_Cmd(SPI2, ENABLE);
    
}
 
int main(void)
{
    Allini();
    
    CS_ON();
    
    SPI_SendData8(SPI2, 0x8B);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET) {}
    SPIdata = SPI_ReceiveData8(SPI2);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET) {}
    SPI_SendData8(SPI2, 0x00);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET) {}
    SPIdata = SPI_ReceiveData8(SPI2);
        
    CS_OFF();
}
Ииииииии... ничего. SPI тактируется, а DR - пустой...
Что я делаю не так?((
0
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
01.04.2017, 10:53
Цитата Сообщение от Basitin Посмотреть сообщение
SPI_ini.SPI_CPOL = SPI_CPOL_High;
* * SPI_ini.SPI_CPHA = SPI_CPHA_2Edge;
я не очень помню что конкретно делают эти настройки, но проблема, в частности, может быть в них. Согласно ДШ на ваш АЦП у него изменение сигнала происходит с первого бита, а сбор данных - по фронту. Полярность MOSI ожидается "с нуля". Вариантов возможных конфигураций не так и много, поэтому, я рекомендую попробовать их все последовательно.
(начиная с CPOL_Low и CPHA_1Edge).
Что касается самих данных - тут имеет смысл посмотреть на стр.17 ДШ. Что-то там как-то много данных надо кидать. Ваши "0x8B" должны быть чем-то обоснованы. Попробуйте разобраться, что это за биты и режимы.
1
1 / 1 / 0
Регистрация: 17.07.2015
Сообщений: 27
01.04.2017, 15:43  [ТС]
Цитата Сообщение от Voland_ Посмотреть сообщение
я не очень помню что конкретно делают эти настройки, но проблема, в частности, может быть в них. Согласно ДШ на ваш АЦП у него изменение сигнала происходит с первого бита, а сбор данных - по фронту. Полярность MOSI ожидается "с нуля". Вариантов возможных конфигураций не так и много, поэтому, я рекомендую попробовать их все последовательно.
(начиная с CPOL_Low и CPHA_1Edge).
Что касается самих данных - тут имеет смысл посмотреть на стр.17 ДШ. Что-то там как-то много данных надо кидать. Ваши "0x8B" должны быть чем-то обоснованы. Попробуйте разобраться, что это за биты и режимы.
"0x8B" - я написал от балды. Чтобы хоть что-то занести в DR. Первоначально я пытался настроить ацп:

ADC313029282726252423222120191817161514. . . 0 - (32 бит)
                    
IN1"0"ENSGL0DDA2A1A0EN2IMFAFBSPD      
IN100101111000000000. . . 0
(После "FB" не важно какие биты стоят, они не учитываются)

Переведя из двоичной системы в 16-ричную, получилось: 0x12F0. Если я правильно перевёл. "SPI_SendData8(SPI2, 0x12F0);"

Я перебрал все варианты настройки SPI, что вы предложили, но ничего не получилось. DR - пустой по прежнему.

Что странно флаг "BSY" всё время срабатывает, как будто,всё же, что-то пошло по SPI. Но это "что-то" должно было сначала попасть в DR? Ведь так?
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,867
01.04.2017, 16:44
Цитата Сообщение от Basitin Посмотреть сообщение
SPI_SendData8
насколько я помню, сия функция передает 8 битные данные, а ты впихиваешь 16 битные
посмотри есть ли функция SPI_SendData16
1
1 / 1 / 0
Регистрация: 17.07.2015
Сообщений: 27
02.04.2017, 07:31  [ТС]
Цитата Сообщение от ValeryS Посмотреть сообщение
насколько я помню, сия функция передает 8 битные данные, а ты впихиваешь 16 битные
посмотри есть ли функция SPI_SendData16
Первоначально стояла передача в 16 бит. Но для примера я изменил её на 8 (пытаясь передать хоть что-то, так как я думал что регистр ограничен в 8 бит).
Но и так DR пустой.

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main(void)
{
    Allini();
    while(1) 
    {
    CS_ON();
    
    SPI_I2S_SendData16(SPI2, 0x12F0);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET) {}
    SPIdata = SPI_I2S_ReceiveData16(SPI2);
        
    CS_OFF();
    }
}
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,867
02.04.2017, 07:59
Цитата Сообщение от Basitin Посмотреть сообщение
DR пустой
тут такая штука
DR это регистр и для чтения и для записи
Записываешь что должно уйти, а считываешь что придет,так может у тебя ничего не приходит
попробуй вручную
C
1
SPI2->DR=xxx;
1
1 / 1 / 0
Регистрация: 17.07.2015
Сообщений: 27
02.04.2017, 10:03  [ТС]
Цитата Сообщение от ValeryS Посмотреть сообщение
тут такая штука
DR это регистр и для чтения и для записи
Записываешь что должно уйти, а считываешь что придет,так может у тебя ничего не приходит
попробуй вручную
В первых примерах, я забивал вручную.
Сейчас снова попробовал, предварительно все затактировал с помощью библиотеки:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include "stm32f0xx.h"     
#include "stm32f0xx_rcc.h"
#include "stm32f0xx_gpio.h"
#include "stm32f0xx_spi.h"
 
#define CS_ON() GPIO_ResetBits(GPIOB, GPIO_Pin_12)
#define CS_OFF() GPIO_SetBits(GPIOB, GPIO_Pin_12)
 
uint16_t SPIdata=0;
 
void Allini(void)
{
    GPIO_InitTypeDef GPIO_spi;
    SPI_InitTypeDef SPI_ini;
    
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
    GPIO_spi.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_spi.GPIO_Mode = GPIO_Mode_AF; 
    GPIO_spi.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_spi.GPIO_OType = GPIO_OType_PP;
    GPIO_spi.GPIO_PuPd = GPIO_PuPd_NOPULL;
    
    GPIO_Init(GPIOB, &GPIO_spi);
    
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_1);
    
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
    GPIO_spi.GPIO_Pin = GPIO_Pin_12;
    GPIO_spi.GPIO_Mode = GPIO_Mode_OUT; 
    GPIO_spi.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_spi.GPIO_OType = GPIO_OType_PP;
    GPIO_spi.GPIO_PuPd = GPIO_PuPd_NOPULL;
    
    GPIO_Init(GPIOB, &GPIO_spi);
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
    SPI_ini.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_ini.SPI_Mode = SPI_Mode_Master;
    SPI_ini.SPI_DataSize = SPI_DataSize_16b;
    SPI_ini.SPI_CPOL = SPI_CPOL_Low; 
    SPI_ini.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_ini.SPI_NSS = SPI_NSS_Soft;
    SPI_ini.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
    SPI_ini.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_ini.SPI_CRCPolynomial = 7;
    
    SPI_Init(SPI2, &SPI_ini);
    
    SPI_Cmd(SPI2, ENABLE);
    
}
 
int main(void)
{
    Allini();
    while(1) 
    {
    CS_ON();
    SPI2->DR = 0x12F0;
    /*SPI_I2S_SendData16(SPI2, 0x12F0);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET) {}
    SPIdata = SPI_I2S_ReceiveData16(SPI2);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET) {}
    SPI_I2S_SendData16(SPI2, 0x00);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET) {}
    SPIdata = SPI_I2S_ReceiveData16(SPI2);*/
        
    CS_OFF();
    }
}
В режиме отладки, даже если я ничего не получаю, а просто заношу в DR, я же должен видеть, как в этот регистр я что-то заношу, так?
Миниатюры
Передача данных по SPI, между АЦП и микроконтроллером  
0
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
03.04.2017, 10:43
Цитата Сообщение от Basitin Посмотреть сообщение
я же должен видеть, как в этот регистр я что-то заношу, так?
не факт. Такие регистры имеют совершенно разные данные при чтении и записи, так что совсем не обязательно даже в дебаггере вы увидите СВОИ данные. Скорее всего там будут данные, принимаемые приемником.

Вы проверьте прежде всего клоки, сделайте некоторую паузу между спадом и фронтом CS, и посчитайте количество бит посылки. Их должно быть 32, как я понимаю. АЦП - хоть и сложная довольно схематехнически вещь, она довольно "тупая" в плане цифрового интерфейса. По сути же это просто стейт-машина, которую нужно "запустить" в том виде, который вам нужен, строго по документации. Обычно, шаг вправо-влево - расстрел, т.к. стейтмашина просто неправильно сработает. И еще - ваши примеры имеют чтение АЦП в переменную, значение которой никак не используется. Соответственно, компилятор вполне возможно, выкинул ее и значение ее вы не увидите. Объявите ее 'volatile uint16_t' для пущей верности.
1
1 / 1 / 0
Регистрация: 17.07.2015
Сообщений: 27
04.04.2017, 11:09  [ТС]
Обнаружилась интересная ошибка. Оказывается надо пины под SPI заводить в AF0, а не в AF1, как это делал я. Теперь я хоть что-то да передаю.
Теперь программа выглядит так (Франкенштейн какой-то - смесь стандартной библиотеки и STM-овской):

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include "stm32f0xx.h"     
#include "stm32f0xx_rcc.h"
#include "stm32f0xx_gpio.h"
#include "stm32f0xx_spi.h"
#include "stm32f0xx.h"
 
#define CS_ON() GPIO_ResetBits(GPIOB, GPIO_Pin_12)
#define CS_OFF() GPIO_SetBits(GPIOB, GPIO_Pin_12)
 
#define BAUDRATE 9600
#define TAKT 8000000
#define SPI1_DR_8bit          (*(__IO uint8_t *)((uint32_t)&(SPI1->DR)))
 
 
/*
void Delay_ms(uint32_t ms)
{
        volatile uint32_t nCount;
 
        nCount=(8000000/10000)*ms;
        for (; nCount!=0; nCount--);
}
 
*/
void Allini(void)
{
 
        /* Включаем тактирование порта */    
        RCC -> AHBENR |= (RCC_AHBENR_GPIOBEN);   
     
        /* Настройки порта PORT B*/
    
      // Настраиваем выхода
        GPIOB -> MODER  |=  GPIO_MODER_MODER12_0;   // Устанавливаем бит MODE0 для выводов порта (режим GPIO)
            
        GPIOB -> OTYPER &=  (~GPIO_OTYPER_OT_12);   // Сбрасываем бит OT для выводов (режим Push-Pull) 
 
        /* Настройка SPI2 */
    
        GPIOB->MODER &= (~GPIO_MODER_MODER14);      // Сбрасываем бит MODE (режим - вход)
        GPIOB->PUPDR &= (~GPIO_PUPDR_PUPDR14);  // Сбрасываем биты PUPDR (режим без подтяжек - No pull-up, pull-down)
        GPIOB->MODER &= ~(GPIO_MODER_MODER15 | GPIO_MODER_MODER13);  //Push-Pul
        GPIOB->MODER |= GPIO_MODER_MODER15_1 | GPIO_MODER_MODER14_1 | GPIO_MODER_MODER13_1; //Alternate function
        //GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_15 | GPIO_OTYPER_OT_14 | GPIO_OTYPER_OT_13 | GPIO_OTYPER_OT_11); 
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_0);
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_0);
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_0);
        
        RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; //Тактирование модуля SPI2
        SPI2->CR1 |= SPI_CR1_BR; //Baud rate = Fpclk/256
        SPI2->CR1 |= SPI_CR1_CPOL | SPI_CR1_CPHA;  //Полярность тактового сигнала
        SPI2->CR1 &= ~SPI_CR1_CPHA; //Фаза тактового сигнала
        SPI2->CR2 |= SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2; //8 бит данных
        SPI2->CR1 &= ~SPI_CR1_LSBFIRST; //MSB передается первым
        SPI2->CR1 &= ~SPI_CR1_SSM; //Программный режим NSS
        SPI2->CR1 |= SPI_CR1_SSI; //Аналогично состоянию, когда на входе NSS высокий уровень
        SPI2->CR2 |= SPI_CR2_SSOE; //Вывод NSS - выход управления slave select
        SPI2->CR1 |= SPI_CR1_MSTR; //Режим Master
        SPI2->CR1 |= SPI_CR1_SPE; //Включаем SPI2
    
  return;
    
}
 
int main(void)
{
    Allini();
    while(1) 
    {
    CS_ON();
        
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); // ждём, освобождения SPI_DR
    SPI_SendData8(SPI2, 0xA7);
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); // ждём, освобождения SPI_DR
    SPI_SendData8(SPI2, 0x88);
 
    //SPIdata = SPI_ReceiveData8(SPI2);
 
    CS_OFF();
    }
}
Потыкал осцилом и оказалось что инфу передают ВСЕ пины, даже МИСО! Из за чего я не могу получать хоть сколько-то осмысленные данные с АЦП. =\

Перепроверил все настройки порта В и SPI, должно все работать.

Цитата Сообщение от Voland_ Посмотреть сообщение
Объявите ее 'volatile uint16_t' для пущей верности.
А если в тупую биты слать, не создавая переменные?
1
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
04.04.2017, 11:14
Цитата Сообщение от Basitin Посмотреть сообщение
Обнаружилась интересная ошибка. Оказывается надо пины под SPI заводить в AF0, а не в AF1, как это делал я.
вы ж сознательно (меня по крайней мере) ввели в заблуждение словами:
Цитата Сообщение от Basitin Посмотреть сообщение
Воспользовался STM-овской библиотекой, для МК моей серии:
STM, не смотря на общие имена и близкиеспецификации - часто имеют совершенно другую периферию внутри. Соответственно, как только появляется вопрос с периферией, надо лезть в Reference Manual или смотреть примеры конкретно для вашего чипа (а не для семейства, как в AVR). Иначе постоянно будете натыкаться на подобные нестыковки.
1
1 / 1 / 0
Регистрация: 17.07.2015
Сообщений: 27
04.04.2017, 11:37  [ТС]
Цитата Сообщение от Voland_ Посмотреть сообщение
вы ж сознательно (меня по крайней мере) ввели в заблуждение словами:
Прошу прощения, просто перечитывал даташит для STM32F051xx и наткнулся на таблицу, где указаны AF для разных устройств в МК. В первый раз не обратил на нее внимания, и просто взял AF из файла stm32f0xx.h.

Что касается примеров в референц мануале, то я настройку SPI выполнял аналогично.
Миниатюры
Передача данных по SPI, между АЦП и микроконтроллером  
0
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
04.04.2017, 15:02
Цитата Сообщение от Basitin Посмотреть сообщение
просто перечитывал даташит для STM32F051xx и наткнулся на таблицу, где указаны AF для разных устройств в МК
Понятно. По-видимому, просто ошибка в библиотеке от ST. Просто судя по комментариям - они, возможно, сформированы автоматически. а значит ошибки быть не должно.
0
1 / 1 / 0
Регистрация: 17.07.2015
Сообщений: 27
05.04.2017, 06:13  [ТС]
Цитата Сообщение от Voland_ Посмотреть сообщение
Понятно
Я так и не понял, почему у меня МК что-то шлёт в MISO. : (
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
05.04.2017, 06:13
Помогаю со студенческими работами здесь

Передача данных через SPI ATmega8
Не передаются данные через шину, не понимаю почему. Передаю массив данных, который содержит в себе картинку 8 на 8 пикселей. По схеме...

передача и приём данных по SPI на STM32
Здравствуйте, уважаемые форумчане. Пытаюсь наладить общение STM32f723IE, что на плате DISCOVERY и STM32F407VG на дешевой китайской...

Передача данных с АЦП по USART
Здравствуйте уважаемые форумчане подскажите пожалуйста я взял рабочий код по работе АЦП и DMA настроил USORT. DMA берет значения АЦП...

Передача данных от АЦП по USART
Здравствуйте, есть задача: оцифровывать аналоговый сигнал на нескольких ножках МК (stm32f411) и полученный результат отправлять в ПК по...

Передача данных, вопросы по SPI и SSI интерфейсам
Привет всем. Я работаю над собственным электроприводом, обзавелся силовым драйвером для шагового двигателя (TMC246A-PA) угловым энкодером...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru