|
STM32 <-spi-> внешний ADC |
|
|
|
May 27 2013, 15:51
|
Группа: Участник
Сообщений: 10
Регистрация: 27-05-13
Пользователь №: 76 996

|
Господа, помогите разобраться. У меня есть STM32F3-Discovery, я хочу подключить к нему через SPI ацп AD7738 ( pdf). Решил использовать SPI2, в даташите STM32F3 прочитал, что в SPI2 задействованы ноги PB13, PB14, PB15. Настроил GPIO для этих пинов, настроил GPIO для RDY пина, на который пишется нолик, когда АЦП завершает преобразование (выбрал PD10), создал SPI2 с некими параметрами. Для конфигурации я сделал ряд функций, которыми можно изменять параметры регистров, чтобы каждый раз не писать 0b00... (см. дефайны и ADC_ функции в коде) Суть в том, что я использовал сначала пример с прерываниями и он работал, но через ж... не совсем как я хочу. Там я отправляю байтики функцией SPI_I2S_SendData16 и они приходят в функцию прерывания. Проблема в том, что я не могу понять, что я читаю, но по данным догадался, что приходит стандартное значение регистра данных (8000h), на датчик не реагирует АЦП. Поэтому я погуглил еще и просто сделал функции для чтения-записи 8бит данных вместо прерываний. Далее пишу 0x42 (перед mode-регистром, до начала преобразования), чтобы достать версию чипа, должно прийти "33" (dec), но приходит 0. С прерываниями работало и приходило 33 (и это подходило под описание регистра ревизии). Также не приходит стандартное значение регистра данных, вместо этого приходит тупо 0. В чем ошибка моего варианта? Я подозреваю, что само соединение как-то не правильно настроено. Код прилагаю Код #include "main.h" #include <stdbool.h> #include <math.h> #include "usb_CDC.h" #include "stm32f30x_gpio.h" #include "stm32f30x_spi.h"
/*******************************************************************************/ __IO uint32_t TimingDelay = 0; __IO uint32_t UserButtonPressed = 0; __IO uint8_t DataReady = 0; __IO uint8_t PrevXferComplete = 1; __IO uint32_t USBConnectTimeOut = 100; volatile int rx, rx_data;
union Pack16bitk{ char b[sizeof(short)]; short sval; } Package16;
/* * AIN0: 000 * AIN1: 001 * AIN2: 010 * AIN3: 011 * AIN4: 100 * AIN5: 101 * AIN6: 110 * AIN7: 111 */
#define SELECH 0b00000111
#define IOPR_P0_OUTPUT_0 0b00000000 #define IOPR_P0_OUTPUT_1 0b10000000 #define IOPR_P0_DIR_AIN 0b01000000 #define IOPR_P0_DIR_AOUT 0b00000000 #define IOPR_P1_DIR_DIN 0b00100000 #define IOPR_P1_DIR_DOUT 0b00000000 #define IOPR_RDYFN_ANY 0b00000000 #define IOPR_RDYFN_ALL 0b00001000 #define IOPR_SYNC_ON 0b00000001 #define IOPR_SYNC_OFF 0b00000000
#define CHSETR_BUF_ENABLE 0b00000000 #define CHSETR_BUF_DISABLE 0b10000000 #define CHSETR_AINCONF_0 0b00000000 #define CHSETR_AINCONF_1 0b01100000 #define CHSETR_STATOPT_P1 0b00010000 #define CHSETR_STATOPT_RDY 0b00000000 #define CHSETR_ENABLE_ENABLE 0b00001000 #define CHSETR_ENABLE_DISABLE 0b00000000 #define CHSETR_RANGE_0 0b00000100 // +-2.5V #define CHSETR_RANGE_1 0b00000101 // 0V to +2.5V #define CHSETR_RANGE_2 0b00000000 // +-1.25V #define CHSETR_RANGE_3 0b00000001 // 0V to +1.25V #define CHSETR_RANGE_4 0b00000010 // +-0.625V #define CHSETR_RANGE_5 0b00000011 // 0V to +0.625V
#define CHCONVTIMER_CHOP_ON 0b10000000 #define CHCONVTIMER_CHOP_OFF 0b00000000 #define CHCONVTIMER_FILTER_0 0b01111111 //FW=127, Conv.Time = 2686 us, Out data rate = 372Hz [With chopping enabled] #define CHCONVTIMER_FILTER_1 0b00101110 //FW=46, Conv.Time = 999 us, Out data rate = 1001 Hz #define CHCONVTIMER_FILTER_2 0b00010001 //FW=17, Conv.Time = 395 us, Out data rate = 2534 Hz #define CHCONVTIMER_FILTER_3 0b00001000 //FW=8, Conv.Time = 207 us, Out data rate = 4826 Hz #define CHCONVTIMER_FILTER_4 0b00000100 //FW=4, Conv.Time = 124 us, Out data rate = 8074 Hz #define CHCONVTIMER_FILTER_5 0b00000010 //FW=2, Conv.Time = 82 us, Out data rate = 12166 Hz
#define MODER_MODE_CONTINUOUS 0b00100000 #define MODER_MODE_SINGLE 0b01000000 #define MODER_CLKDIS_ON 0b00010000 #define MODER_CLKDIS_OFF 0b00000000 #define MODER_DUMP_ON 0b00001000 #define MODER_DUMP_OFF 0b00000000 #define MODER_CONTRD_ON 0b00000100 #define MODER_CONTRD_OFF 0b00000000 #define MODER_BITS_24 0b00000010 #define MODER_BITS_16 0b00000000 #define MODER_CLAMP_ON 0b00000001 #define MODER_CLAMP_OFF 0b00000000
/*******************************************************************************/ void USB_Config(void){ Set_System(); Set_USBClock(); USB_Interrupts_Config(); USB_Init();
while ((bDeviceState != CONFIGURED)&&(USBConnectTimeOut != 0)) {} }
/*******************************************************************************/ void SPI_Config(void){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_5); GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_5); GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_5);
GPIO_InitTypeDef port;
port.GPIO_Mode = GPIO_Mode_AF; port.GPIO_OType = GPIO_OType_PP; port.GPIO_PuPd = GPIO_PuPd_DOWN; port.GPIO_Speed = GPIO_Speed_50MHz;
//SCK -> PB13 | MISO -> PB14 | MOSI -> PB15 port.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_Init(GPIOB, &port);
SPI_InitTypeDef spi; spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex; spi.SPI_Mode = SPI_Mode_Master; spi.SPI_DataSize = SPI_DataSize_8b; spi.SPI_CPOL = SPI_CPOL_High; spi.SPI_CPHA = SPI_CPHA_2Edge; spi.SPI_NSS = SPI_NSS_Soft; spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; spi.SPI_FirstBit = SPI_FirstBit_MSB; spi.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &spi); SPI_Cmd(SPI2, ENABLE); //Включение SPI }
uint8_t SPI_SendRead8(uint8_t ToSend8){ while((SPI2->SR & SPI_I2S_FLAG_TXE) == RESET); SPI2->DR = ToSend8; while ((SPI2->SR & SPI_I2S_FLAG_RXNE) == RESET); return (SPI2->DR); }
void SPI_Send8(uint8_t ToSend8){ while((SPI2->SR & SPI_I2S_FLAG_TXE) == RESET); SPI2->DR = ToSend8; while ((SPI2->SR & SPI_I2S_FLAG_RXNE) == RESET); uint8_t dummy = (SPI2->DR); }
void ADC_Reset(){ SPI_Send8(0x00); SPI_Send8(0xff); SPI_Send8(0xff); SPI_Send8(0xff); SPI_Send8(0xff); }
void ADC_IOpr(uint8_t P0, uint8_t P1, uint8_t P0_DIR, uint8_t P1_DIR, uint8_t RDYFN, uint8_t SYNC){ SPI_Send8(0b00000001); //IO Port Register SPI_Send8(P0+P1+P0_DIR+P1_DIR+RDYFN+SYNC); }
void ADC_ChSetr(uint8_t BUFOFF, uint8_t AINCONF, uint8_t STATOPT, uint8_t ENABLE, uint8_t RANGE){ SPI_Send8(0b00101000+SELECH); //Channel setup register SPI_Send8(BUFOFF+AINCONF+STATOPT+ENABLE+RANGE); }
void ADC_ChConvTimr(uint8_t CHOP, uint8_t FILTERWORD){ SPI_Send8(0b00110000+SELECH); //Channel conversion time register SPI_Send8(CHOP+FILTERWORD); }
void ADC_Moder(uint8_t MODER_MODE, uint8_t CLKDIS, uint8_t DUMP, uint8_t CONTRD, uint8_t MODER_BITS, uint8_t CLAMP){ SPI_Send8(0b00111000+SELECH); //Mode register SPI_Send8(MODER_MODE+CLKDIS+DUMP+CONTRD+MODER_BITS+CLAMP); }
/*******************************************************************************/ int main(void){ SystemInit(); RCC_ClocksTypeDef RCC_Clocks; RCC_GetClocksFreq(&RCC_Clocks); SysTick_Config(RCC_Clocks.HCLK_Frequency / 100);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE); GPIO_InitTypeDef portd; portd.GPIO_Mode = GPIO_Mode_IN; portd.GPIO_PuPd = GPIO_PuPd_DOWN; portd.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOD, &portd);
USB_Config(); SPI_Config();
ADC_Reset(); ADC_IOpr(IOPR_P0_OUTPUT_1, IOPR_P0_OUTPUT_1, IOPR_P0_DIR_AIN, IOPR_P1_DIR_DOUT, IOPR_RDYFN_ANY, IOPR_SYNC_OFF); ADC_ChSetr(CHSETR_BUF_ENABLE, CHSETR_AINCONF_1, CHSETR_STATOPT_P1, CHSETR_ENABLE_ENABLE, CHSETR_RANGE_1); ADC_ChConvTimr(CHCONVTIMER_CHOP_ON, CHCONVTIMER_FILTER_2);
uint8_t ADC_Revision = SPI_SendRead8(0x42); //Должно быть 0x21
ADC_Moder(MODER_MODE_CONTINUOUS, MODER_CLKDIS_ON, MODER_DUMP_OFF, MODER_CONTRD_OFF, MODER_BITS_16, MODER_CLAMP_OFF);
while (1){ if(GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_10) == 0){ //1=high 0=low SPI_Send8(0b1001000+SELECH);//1001000-1001111 Package16.b[0] = SPI_SendRead8(0x00); Package16.b[1] = SPI_SendRead8(0x00); USB_Send_Short(Package16.sval); } Delay(50); } }
/*******************************************************************************/ void Delay(__IO uint32_t nTime){ TimingDelay = nTime; while(TimingDelay != 0); }
/*******************************************************************************/ void TimingDelay_Decrement(void){ if (TimingDelay != 0x00) { TimingDelay--; } }
Сообщение отредактировал undef1ned - May 27 2013, 15:53
|
|
|
|
|
 |
Ответов
|
May 27 2013, 22:41
|
Группа: Участник
Сообщений: 10
Регистрация: 27-05-13
Пользователь №: 76 996

|
Да, у меня CS (4 пин) подключен к GND на stm32f3-discovery, я проверил Еще приведу свой код с прерываниями, где поочередно приходят значения 0x8000, 0x80, 0x00, а кстати если отключить питание датчиков то приходит 0xE080, 0xE0, 0x8000 Собственно, та же программа, но есть ф-я Код void SPI2_IRQHandler(){ if (SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_RXNE) == SET){ uint16_t spi_data16 = 0x00; spi_data16 = SPI_I2S_ReceiveData16(SPI2); USB_Send_Short(spi_data16); } } В ней я ставлю бряк на USB_Send_Short() и смотрю spi_data16. Конф-я SPI, вроде такая же, ну помимо 16 бит размера, но с 8 бит то же самое: Код /*******************************************************************************/ void SPI_Config(void){ RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_5); GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_5); GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_5);
port.GPIO_Mode = GPIO_Mode_AF; port.GPIO_OType = GPIO_OType_PP; port.GPIO_PuPd = GPIO_PuPd_DOWN; port.GPIO_Speed = GPIO_Speed_50MHz;
//SCK -> PB13, MOSI -> PB15 port.GPIO_Pin = GPIO_Pin_15; GPIO_Init(GPIOB, &port);
port.GPIO_Pin = GPIO_Pin_13; GPIO_Init(GPIOB, &port);
//MISO -> PB14 port.GPIO_Pin = GPIO_Pin_14; GPIO_Init(GPIOB, &port);
//SPI_StructInit(&spi); spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex; spi.SPI_Mode = SPI_Mode_Master; spi.SPI_DataSize = SPI_DataSize_16b;//16 spi.SPI_CPOL = SPI_CPOL_High; spi.SPI_CPHA = SPI_CPHA_2Edge; spi.SPI_NSS = SPI_NSS_Soft; spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; spi.SPI_FirstBit = SPI_FirstBit_MSB; spi.SPI_CRCPolynomial = 7; SPI_Init(SPI2, &spi); } Вместо ADC_ функций тупо шлю заранее записанные байты: Код void ADC_Config(void){ //00h + FFh + FFh + FFh + FFh (RESET) SPI_SendData8(SPI2, 0x00); SPI_SendData8(SPI2, 0xff); SPI_SendData8(SPI2, 0xff); SPI_SendData8(SPI2, 0xff); SPI_SendData8(SPI2, 0xff);
//Configure SPI_SendData8(SPI2, 0b00000001); //IO Port Registe SPI_SendData8(SPI2, 0b11110000); //
SPI_SendData8(SPI2, 0b00101000+SELECH); //Channel setup register SPI_SendData8(SPI2, 0b00011100); //+-2.5V, Single-ended ENABLE
SPI_SendData8(SPI2, 0b00110000+SELECH); //ch. conv. time, 110000-110111 SPI_SendData8(SPI2, 0b10010001); // }
void ADC_SetMODER(void){ SPI_SendData8(SPI2, 0b00111000+SELECH); //Mode register, 00111111-00111000 SPI_SendData8(SPI2, 0x00100000); } Ну и здесь вот с настрйокой прерываний: Код int main(void){ __enable_irq(); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE); GPIO_InitTypeDef portd; portd.GPIO_Mode = GPIO_Mode_IN; portd.GPIO_PuPd = GPIO_PuPd_DOWN; portd.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOD, &portd);
SystemInit(); RCC_GetClocksFreq(&RCC_Clocks); SysTick_Config(RCC_Clocks.HCLK_Frequency / 100); USB_Config();
SPI_Config(); NVIC_EnableIRQ(SPI2_IRQn); SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE); SPI_Cmd(SPI2, ENABLE); SPI_NSSInternalSoftwareConfig(SPI2, SPI_NSSInternalSoft_Set);
ADC_Config(); ADC_SetMODER();
while (1){ //Poll RDY pin if(GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_10) == 0){ //1=high 0=low SPI_SendData8(SPI2, 0b1001000+SELECH);//0x4F } Delay(50); } } Такие дела. Конечно неправильно отправлять просто 0x4F, там в дш после него еще 2 раза по 0х00 идет. Если поставить SPI_SendData8(0x00) 2 раза, то в ответ на это просто приходят нули (по крайней мере в этом все отличие).
Сообщение отредактировал undef1ned - May 27 2013, 22:42
|
|
|
|
Сообщений в этой теме
undef1ned STM32 <-spi-> внешний ADC May 27 2013, 15:51 artkam А где у Вас в коде управление ногой CHIP SELECT (C... May 27 2013, 20:49 undef1ned Цитата(artkam @ May 28 2013, 00:49) А где... May 27 2013, 21:38 artkam Поверьте, CS обязательно требуется притягивать к з... May 27 2013, 22:10 artkam Приведите пожалуйста схему подключения АЦП к МК... May 28 2013, 12:44 undef1ned Ну собственно, от AD7738 к мк идут только SCLK, RD... May 28 2013, 13:13 artkam Отсоедините CS от земли и подключите его к свободн... May 28 2013, 13:29 undef1ned Да, я так попробую сделать сейчас. спасибо за подс... May 29 2013, 08:12 undef1ned Вобщем подключил SS и дергаю его когда передаю-пол... May 29 2013, 14:05 AHTOXA Цитата(undef1ned @ May 29 2013, 20:05) По... May 29 2013, 16:47 undef1ned Я думал, что то что я записываю 0х42 это и есть ну... May 29 2013, 16:56 AHTOXA Как, по-вашему, АЦП по первому биту команды 0x42 д... May 29 2013, 17:14  undef1ned Цитата(AHTOXA @ May 29 2013, 21:14) Как, ... May 29 2013, 18:11   AHTOXA Хм, похоже у вас SPI в 16-битном режиме. Где-то з... May 29 2013, 18:19 undef1ned Я когда этот макрос применяю, у меня вообще зависа... May 29 2013, 19:03 undef1ned Если я пишу в CR2 датасайз, соответствующий 7 бит ... May 29 2013, 22:56 AHTOXA Да уж. У меня до F3 пока руки не доходят. Но думаю... May 30 2013, 17:48
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|