реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> STM32_SPI_AD7794, Принимаю из АЦП подряд 3 байта, они абсолютно одинаковые.
nx6310
сообщение Jul 7 2010, 04:19
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 72
Регистрация: 28-06-10
Пользователь №: 58 174



Связь STM32 c АЦП AD7794 через SPI. Использую стандартные библиотеки от производителя.Прога на Atomic TrueStudio (аналог Eclipse ). Для чтения из АЦП 24 битных данных использую псоледовательно прием 3 байтов. При этом они получаются абсолютно одинаковыми по значению. Кто нибудь сталкивался с этим?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 7 2010, 10:59
Сообщение #2


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Чтобы прочитать байт из SPI, надо записать туда какой-либо байт. Вы это учли?


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
nx6310
сообщение Jul 7 2010, 11:08
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 72
Регистрация: 28-06-10
Пользователь №: 58 174



Я пользуюсь стандартной библиотечной функцией. АЦП нормально преобразует. На его входе акселерометр стоит, при его наклоне данные с АЦП меняются. Даные по SPI конроллер получает. Только они дублируются. Я последовательно получаю старшый байт, средний байт и младший байт. В итоге должно получиться 24-х разрядное число. Но уменя все эти три байта одинаковые. Не знаю даже в чем ошибся.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 7 2010, 12:04
Сообщение #4


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Давайте код, посмотрим.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
nx6310
сообщение Jul 8 2010, 02:38
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 72
Регистрация: 28-06-10
Пользователь №: 58 174



Вот код. АЦП в режиме постоянного преобразования.
Код
     while (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_6)!=0){}
        // SPI_I2S_SendData(SPI2, 0b01011000);
    //GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_SET);
// while (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_8)!=0){}    //проверка окончания преобразования
  //GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_RESET);
         while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
      ADCL = SPI_I2S_ReceiveData(SPI2);
     // while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE)==RESET){}
      //Delay(0x6ffff);
       ADCM = SPI_I2S_ReceiveData(SPI2);
     // while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE)==0){}
        //  Delay(0x6ffff);
       ADCH = SPI_I2S_ReceiveData(SPI2);
     // while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE)==0){}
      //GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_SET);
      ADC_Data=ADCH*0x10000+ADCM*0x100+ADCL;

Ниже стандартные библиотечные функции обмена по SPI
Код
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data)
{
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(SPIx));
  
  /* Write in the DR register the data to be sent */
  SPIx->DR = Data;
}

/**
  * @brief  Returns the most recent received data by the SPIx/I2Sx peripheral.
  * @param  SPIx: where x can be
  *   - 1, 2 or 3 in SPI mode
  *   - 2 or 3 in I2S mode
  * @retval The value of the received data.
  */
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx)
{
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(SPIx));
  /* Return the data in the DR register */
  return SPIx->DR;
}
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 8 2010, 07:22
Сообщение #6


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(nx6310 @ Jul 8 2010, 08:38) *
Код
     while (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_6)!=0){}
         while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
      ADCL = SPI_I2S_ReceiveData(SPI2);
       ADCM = SPI_I2S_ReceiveData(SPI2);
       ADCH = SPI_I2S_ReceiveData(SPI2);
      ADC_Data=ADCH*0x10000+ADCM*0x100+ADCL;


Мда... Повторяю свою первую реплику:

Цитата(AHTOXA @ Jul 7 2010, 16:59) *
Чтобы прочитать байт из SPI, надо записать туда какой-либо байт. Вы это учли?


Где запись перед чтением?

Код
    SPI_I2S_SendData(SPI2, 0);
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
    ADCL = SPI_I2S_ReceiveData(SPI2);

    SPI_I2S_SendData(SPI2, 0);
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
    ADCM = SPI_I2S_ReceiveData(SPI2);

    SPI_I2S_SendData(SPI2, 0);
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
    ADCH = SPI_I2S_ReceiveData(SPI2);


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jul 9 2010, 17:50
Сообщение #7


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Да. Стандартная наколка spi-нубов:-)
Чем SPI хорош - это просто тупейший сдвиговй регистр как у мастера так и у слейва, соединённые в кольцо.
И для произведения обмена этими регистрами (по сути ни чтения ни записи отдельно не существует) нужны тактовые имульсы в размере N-штук, где N-разрядность регистра.
Ну и конечно же нужно выбрать того слейва с кем хочется пообщаться - для этого используют столько линии #CS сколько есть слейвов.
Вот и вся премудрость:-)

ИМХО SPI - самый примитивный интерфейс вообще.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
nx6310
сообщение Jul 12 2010, 03:04
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 72
Регистрация: 28-06-10
Пользователь №: 58 174



А как переключать каналы в АЦП. Я выбираю канал, потом идёт задержка и после этого только преобразование. Но у меня вместо нормального значения выводятся FFFF. Как правильно это делается?
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jul 12 2010, 11:03
Сообщение #9


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Вы datasheet вообще-то открывали?
Уж больно странные вопросы Вы задаёте, даже для раздела начинающих.
Почитайте подумайте, попробуйте.
Если не получилось, то расскажите что и как делали, покажите код, покажите Вашу схему включения.
Иначе долго будете топтаться на месте.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
nx6310
сообщение Jul 12 2010, 11:28
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 72
Регистрация: 28-06-10
Пользователь №: 58 174



Даташит читал. Сначала иницилизирую АЦП. Включаю буфер. Мне надо шесть каналов три на ферозонды три на акселерометры. опора внешняя на 2,5В. использую внутренний генератор.
код инициализации АЦП
Код
void ADC_Configuration(void){
      int i=0b0000000000110000;
GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_RESET); // выбор АЦП CS_AD7794
    SPI_I2S_SendData(SPI2, 0b0000000000101000);    //в буферный регистр (к регистру IO)
     SPI_I2S_SendData(SPI2, 0b0000000000000000);    //настройка выводов АЦП
while (i<=0b0000000000110101){      // здесь циклически калибрую каждый канал ацп по нулю и полной шкале
        SPI_I2S_SendData(SPI2, 0b0000000000010000);    //comunic reg
        SPI_I2S_SendData(SPI2,i);    //config reg ADC - конфигурирую АЦП
        SPI_I2S_SendData(SPI2, 0b0000000000001000);    //comunic reg
        SPI_I2S_SendData(SPI2,0b1000001000001111);    //mode reg ADC IZC-call калибровка нуля
    while (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_6)!=0){}    //проверка окончания преобразования (вывод DOUT/RDY)
                 SPI_I2S_SendData(SPI2, 0b0000000000001000);    //comunic reg
                   SPI_I2S_SendData(SPI2, 0b1010001000001111);    //mode reg ADC IFC-call калибровка полной шкалы
             while (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_6)!=0){}    //проверка окончания преобразования
      GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_RESET);
      i++;
    }
               SPI_I2S_SendData(SPI2, 0b0000000000001000);    //comunic reg после окончания калибровки каждого канала
      SPI_I2S_SendData(SPI2,0b0000001000000110);    //mode reg ADC default mode перевожу АЦП в режим непрерыного преобразования
}


В ходе выполнения программы мне необходимы данные со всех каналов. Кусок получения данных из АЦП для двух каналов представлен ниже


Код
SPI_I2S_SendData(SPI2, 0b0000000000010000);            //комуникац регистр. выбираю регистр конфигурации
SPI_I2S_SendData(SPI2, (0b0000000000010000));        //в котором выбираю канал 0 (буфер включён)
SPI_I2S_SendData(SPI2, 0b0000000001011100);        //в комуникац регистр запрос на получение данны х с АЦП
        while (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_6)!=0){} // есть ли готовые данные в ацп
            AX = SPI_I2S_ReceiveData(SPI2); // считываем старшие 16 бит с АЦП - информативные данные
            Delay(0xaf);
            SPI_DataSizeConfig(SPI2, SPI_DataSize_8b);  // переводим SPi в 8-битный режим
            hrn = SPI_I2S_ReceiveData(SPI2);   // ситываю оставшиеся 8 бит, в этом байте мусор который я не использую
            SPI_DataSizeConfig(SPI2, SPI_DataSize_16b);


SPI_I2S_SendData(SPI2, 0b0000000000010000);            //комуникац регистр.
SPI_I2S_SendData(SPI2, 0b0000000000010001);        //регистр конфигурации выбираю канал 1
Delay(0xfff);                                    // задержка после выбора канала для разрядки конденсатора АЦП, какое бы значение не ставил не помогает
SPI_I2S_SendData(SPI2, 0b0000000001011100);        //режим постоянного преобр.
        while (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_6)!=0){} // есть ли готовые данные в ацп
            AY = SPI_I2S_ReceiveData(SPI2);  // считываем старшие 16 бит с АЦП - информативные данные
            Delay(0xaf);
            SPI_DataSizeConfig(SPI2, SPI_DataSize_8b);
            hrn = SPI_I2S_ReceiveData(SPI2);
            SPI_DataSizeConfig(SPI2, SPI_DataSize_16b);



при считывании данных по USART получаю следующее
Код
Test_AX032934_AY065535_AZ032255_FX032255_FY065535_FZ065535_
Test_AX032932_AY065535_AZ065535_FX065535_FY065535_FZ065535_
Test_AX032932_AY065535_AZ065535_FX065535_FY065535_FZ065535_
Test_AX032932_AY065535_AZ065535_FX065535_FY065535_FZ065535_
Test_AX032930_AY065535_AZ065535_FX065535_FY065535_FZ065535_
Test_AX032930_AY065535_AZ065535_FX065535_FY065535_FZ065535_
Test_AX032930_AY065535_AZ065535_FX065535_FY065535_FZ065535_
Test_AX032932_AY065535_AZ065535_FX065535_FY065535_FZ065535_
Test_AX032930_AY065535_AZ065535_FX065535_FY065535_FZ065535_

По отдельности каждый канал работает нормально. Но вот при переключении каналов получается такая каша. Микроконтроллер STM32f103. Где я мог ошибиться?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 12 2010, 16:53
Сообщение #11


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(nx6310 @ Jul 12 2010, 17:28) *
Код
    while (GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_6)!=0){} // есть ли готовые данные в ацп
    AY = SPI_I2S_ReceiveData(SPI2);  // считываем старшие 16 бит с АЦП - информативные данные

cranky.gif
А где запись в SPI, которая так необходима для считывания?! Ведь я уже два раза выше это написал, пример привёл. Потом ещё demiurg_spb разъяснил...


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
nx6310
сообщение Jul 12 2010, 18:05
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 72
Регистрация: 28-06-10
Пользователь №: 58 174



Она в нутри функции SPI_I2S_ReceiveData(SPI2) в библиотеку засунул я её. С SPI разобрался, данные передаются и принимаются Спасибо вам большое!!!. Шяс проблема с переключением каналов АЦП. Отдельно по каждому коналу данные принимаются нормально (если один канал исчпользовать). В многоканальном режиме полная хрень получаетсяsad.gif
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 12 2010, 18:50
Сообщение #13


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(nx6310 @ Jul 13 2010, 00:05) *
Она в нутри функции SPI_I2S_ReceiveData(SPI2) в библиотеку засунул я её.

А, понятно. Это зря, на мой взгляд. Библиотеку лучше было не трогать, лучше было написать свою функцию. Чтоб не запутаться потом.

Что касается нынешней проблемы - она оттого, что вы неверно читаете готовность АЦП.
Функция GPIO_ReadOutputDataBit(), которую вы используете, читает состояние выходной защёлки порта. То есть, то, что вы записали в этот порт. А для чтения входа надо применять функцию GPIO_ReadInputDataBit().


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
nx6310
сообщение Jul 13 2010, 04:23
Сообщение #14


Участник
*

Группа: Участник
Сообщений: 72
Регистрация: 28-06-10
Пользователь №: 58 174



функцию GPIO_ReadInputDataBit() поменял. Длительность преобразования изменилась. Но вот проблема с переключением кналов осталась.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jul 13 2010, 08:30
Сообщение #15


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(nx6310 @ Jul 13 2010, 10:23) *
функцию GPIO_ReadInputDataBit() поменял.

Везде? В инициализации тоже?
Я не работал с этим АЦП, потому больше не могу помочь. Единственное что скажу - непрерывный режим тут не совсем к месту.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 13:57
Рейтинг@Mail.ru


Страница сгенерированна за 0.13154 секунд с 7
ELECTRONIX ©2004-2016