Discovery STM32F0 problemy s AD prevodem

Dobry den, chci se poradit s AD prevodem na vyvojovem kitu discovery STM32F0, pouzivam vyvojove prostredi CoIDE.

V mem kodu AD prevod nefunguje, ale kdyz zakomentuju inicializaci SPI, tak najednou funguje. Nevim v cem je problem, kdyz kod debuguju, tak se zasekne na radku:

while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));//Processing the conversion

Budu vdecny za kazdou radu.

[code]
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

#include <stm32f0xx.h>
#include <stm32f0xx_gpio.h>
#include <stm32f0xx_rcc.h>
#include <stm32f0xx_usart.h>
#include <stm32f0xx_spi.h>
#include <stm32f0xx_adc.h>
#include <stm32f0xx_misc.h>

#include <stm32f0xx_conf.h>

#define LED_GREEN GPIO_Pin_9
#define LED_BLUE GPIO_Pin_8
#define USER_BUTTON GPIO_Pin_0

//DDS RESET
#define DDS_MSTR_RST GPIO_Pin_4 //PA4

//DDS IO UPDATE
#define DDS_IO_UPD GPIO_Pin_6 //PA6

//DDS SCLK
#define DDS_SCLK GPIO_Pin_5 //PA5

#define DDS_SDIO_0 GPIO_Pin_7 //PA7

//SDIO_3
#define DDS_SDIO_3 GPIO_Pin_0 //PC0

//RANGE_1 R = 5k
#define RANGE_1 GPIO_Pin_13 //PB13

//RANGE_2 R = 50R
#define RANGE_2 GPIO_Pin_14 //PB14

//RANGE_3 R = 500R
#define RANGE_3 GPIO_Pin_15 //PB15

//CHANNEL SWITCH
#define CH_SWITCH GPIO_Pin_6 //PC6

//UART RX PA3
//UART TX PA2

void delay_ad9958(int a)
{
volatile int i,j;

for (i=0 ; i < a ; i++)
{
	j++;
}

return;

}

void io_update(void)
{
GPIO_ResetBits(GPIOA,DDS_IO_UPD);
delay_ad9958(200000);
GPIO_SetBits(GPIOA,DDS_IO_UPD);
delay_ad9958(200000);
GPIO_ResetBits(GPIOA,DDS_IO_UPD);

return;

}

void AD9958_Set_Ch0_Phase(unsigned int phase)// in deg
{
unsigned int PTW = 0;
float temp;
unsigned char CPOW0_1, CPOW0_0;

temp = phase*45.5111;
PTW = (unsigned int)temp;

CPOW0_1 = (PTW & 0x3f00) >> 8;
CPOW0_0 = (PTW & 0x00ff);

GPIO_ResetBits(GPIOC, DDS_SDIO_3);
SPI_SendData8(SPI1,0x00);	//CSR registr
delay_ad9958(20000);
SPI_SendData8(SPI1,0x70);
delay_ad9958(20000);
GPIO_SetBits(GPIOC, DDS_SDIO_3);
delay_ad9958(20000);

GPIO_ResetBits(GPIOC, DDS_SDIO_3);
SPI_SendData8(SPI1,0x05);
delay_ad9958(20000);
SPI_SendData8(SPI1,CPOW0_1);
delay_ad9958(20000);
SPI_SendData8(SPI1,CPOW0_0);
delay_ad9958(20000);
GPIO_SetBits(GPIOC, DDS_SDIO_3);
delay_ad9958(20000);

GPIO_ResetBits(GPIOC, DDS_SDIO_3);
SPI_SendData8(SPI1,0x00);	//CSR registr
delay_ad9958(20000);
SPI_SendData8(SPI1,0xF0);
delay_ad9958(20000);
GPIO_SetBits(GPIOC, DDS_SDIO_3);
delay_ad9958(20000);

io_update();

}

void AD9958_Set_Freq(unsigned int freq)// frequency in Hz
{
unsigned long FTW = 0;
float temp;
unsigned char CFTW0_3, CFTW0_2, CFTW0_1, CFTW0_0;

temp = freq*8.589934592;
FTW = (unsigned long)temp;

CFTW0_3 = (FTW & 0xff000000) >> 24;
CFTW0_2 = (FTW & 0x00ff0000) >> 16;
CFTW0_1 = (FTW & 0x0000ff00) >> 8;
CFTW0_0 = (FTW & 0x000000ff);


GPIO_ResetBits(GPIOC, DDS_SDIO_3);
SPI_SendData8(SPI1,0x04);	//CFTWo registr
delay_ad9958(20000);
SPI_SendData8(SPI1,CFTW0_3);
delay_ad9958(20000);
SPI_SendData8(SPI1,CFTW0_2);
delay_ad9958(20000);
SPI_SendData8(SPI1,CFTW0_1);
delay_ad9958(20000);
SPI_SendData8(SPI1,CFTW0_0);
delay_ad9958(20000);
GPIO_SetBits(GPIOC, DDS_SDIO_3);
delay_ad9958(20000);

io_update();

}

void USART_Send_String(USART_TypeDef* USARTx,volatile char *str)
{
while(*str)
{
while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE) == RESET);
USART_SendData(USARTx,*str);
str++;
}
}

float AD_conversion(char channel)
{
unsigned int pom;
float pom2;

if (channel == 0)
{
	ADC_ChannelConfig(ADC1, ADC_Channel_8, ADC_SampleTime_239_5Cycles);		//8~PB0;9~PB1
}
else
{
	ADC_ChannelConfig(ADC1, ADC_Channel_9, ADC_SampleTime_239_5Cycles);
}


ADC_StartOfConversion(ADC1);

while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));//Processing the conversion

pom = ADC_GetConversionValue(ADC1);

pom2 = (float) pom;
pom2 = pom2*(3.0/4096);

return(pom2);

}

/========== global_variables ==========/
char rec_buffer[10];
unsigned int RxCnt;
unsigned int MyNumber;
unsigned int MyNumberValid;
double R; //rezistor in bridge
/======================================/

int main(void)
{
float value;
char print_value[50];
int i = 0;

GPIO_InitTypeDef GPIO;
USART_InitTypeDef USART;
SPI_InitTypeDef SPI;
ADC_InitTypeDef ADC_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_0);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_0);

/==================USART=====================/
GPIO.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO.GPIO_Mode = GPIO_Mode_AF;
GPIO.GPIO_OType = GPIO_OType_PP;
GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_Init(GPIOA,&GPIO);

USART.USART_BaudRate = 9600;
USART.USART_WordLength = USART_WordLength_8b;
USART.USART_StopBits = USART_StopBits_1;
USART.USART_Parity = USART_Parity_No;
USART.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

USART_Init(USART2, &USART);
USART_Cmd(USART2, ENABLE);

NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

/==================SPI=====================/
GPIO.GPIO_Pin = DDS_SCLK | DDS_SDIO_0;
GPIO.GPIO_Mode = GPIO_Mode_AF;
GPIO.GPIO_OType = GPIO_OType_PP;
GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO.GPIO_Speed = GPIO_Speed_Level_3;
GPIO_Init(GPIOA,&GPIO);

GPIO.GPIO_Pin = DDS_MSTR_RST | DDS_IO_UPD;
GPIO.GPIO_Mode = GPIO_Mode_OUT;
GPIO.GPIO_OType = GPIO_OType_PP;
GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO.GPIO_Speed = GPIO_Speed_Level_1;
GPIO_Init(GPIOA,&GPIO);

GPIO.GPIO_Pin = DDS_SDIO_3;
GPIO.GPIO_Mode = GPIO_Mode_OUT;
GPIO.GPIO_OType = GPIO_OType_PP;
GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO.GPIO_Speed = GPIO_Speed_Level_1;
GPIO_Init(GPIOC,&GPIO);

SPI.SPI_Direction = SPI_Direction_1Line_Tx;
SPI.SPI_Mode = SPI_Mode_Master;
SPI.SPI_DataSize = SPI_DataSize_8b;
SPI.SPI_CPOL = SPI_CPOL_Low;
SPI.SPI_CPHA = SPI_CPHA_1Edge;
SPI.SPI_NSS = SPI_NSS_Soft;
SPI.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI.SPI_FirstBit = SPI_FirstBit_MSB;

SPI_Init(SPI1, &SPI);
SPI_Cmd(SPI1,ENABLE);

/===========DEAFULT_DDS_SETTINGS=============/
GPIO_SetBits(GPIOA, DDS_MSTR_RST);
delay_ad9958(200000);
GPIO_ResetBits(GPIOA, DDS_MSTR_RST);

GPIO_ResetBits(GPIOC, DDS_SDIO_3);
SPI_SendData8(SPI1,0x00);	//CSR registr, channel settings
delay_ad9958(20000);
SPI_SendData8(SPI1,0xF0);
delay_ad9958(20000);
GPIO_SetBits(GPIOC, DDS_SDIO_3);
delay_ad9958(20000);

GPIO_ResetBits(GPIOC, DDS_SDIO_3);
SPI_SendData8(SPI1,0x01);	//FR1 registr, PLL divider
delay_ad9958(20000);
SPI_SendData8(SPI1,0xD0);
delay_ad9958(20000);
SPI_SendData8(SPI1,0x00);
delay_ad9958(20000);
SPI_SendData8(SPI1,0x20);
delay_ad9958(20000);
GPIO_SetBits(GPIOC, DDS_SDIO_3);
delay_ad9958(20000);

//default frequency 100 kHz
AD9958_Set_Freq(100000);

GPIO_ResetBits(GPIOC, DDS_SDIO_3);
SPI_SendData8(SPI1,0x06);	//amplitude 333 mV
delay_ad9958(20000);
SPI_SendData8(SPI1,0b00010000);
delay_ad9958(20000);
SPI_SendData8(SPI1,0x15);
delay_ad9958(20000);
GPIO_SetBits(GPIOC, DDS_SDIO_3);
delay_ad9958(20000);

io_update();
delay_ad9958(20000);

/==================OTHERS=====================/
GPIO.GPIO_Pin = LED_BLUE | LED_GREEN | CH_SWITCH;
GPIO.GPIO_Mode = GPIO_Mode_OUT;
GPIO.GPIO_OType = GPIO_OType_PP;
GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO.GPIO_Speed = GPIO_Speed_Level_1;
GPIO_Init(GPIOC,&GPIO);

GPIO.GPIO_Pin = RANGE_1 | RANGE_2 | RANGE_3;
GPIO.GPIO_Mode = GPIO_Mode_OUT;
GPIO.GPIO_OType = GPIO_OType_PP;
GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO.GPIO_Speed = GPIO_Speed_Level_1;
GPIO_Init(GPIOB,&GPIO);

GPIO.GPIO_Pin = USER_BUTTON;
GPIO.GPIO_Mode = GPIO_Mode_IN;
GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA,&GPIO);

GPIO_SetBits(GPIOC, LED_BLUE);
GPIO_ResetBits(GPIOC, LED_GREEN);

/==================ADC=====================/
GPIO.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO.GPIO_Mode = GPIO_Mode_AN;
GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB,&GPIO);

ADC_DeInit(ADC1);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_Cmd(ADC1, ENABLE);

/=============================================/

while(1)
{

	//if(strcmp(rec_buffer, "m\r")==0)
	//{
		USART_Send_String(USART2,"voltage: ");
		value = AD_conversion(1);
		sprintf(print_value,"%f",value);	//lf for double
		USART_Send_String(USART2, print_value);
		USART_Send_String(USART2,"\r\n");

/*
for(i=0;i<11;i++)
{
rec_buffer* = ‘\0’;
}
RxCnt = 0;
}
*/

	delay_ad9958(1500000);
}

}

/=============================================/
/=============================================/

void USART2_IRQHandler(void)
{
char char_buff;
char buff[50];
int i = 0;

if((USART_GetITStatus(USART2, USART_IT_RXNE) != RESET))
{
	char_buff = (unsigned char)(USART_ReceiveData(USART2));
}

sprintf(buff,"%c",char_buff);
USART_Send_String(USART2,buff);

/*
if(char_buff == 13)
{
MyNumber = atoi(rec_buffer);
if (MyNumber > 0)
{
MyNumberValid = 1;
}

	for(i=0;i<11;i++)
	{
	  rec_buffer* = '\0';
	}

	RxCnt = 0;
}

/
rec_buffer[RxCnt] = char_buff;
RxCnt++;
}
[/code]
*

A jak to prosím vypadá v debugu? (nebo ten nepoužíváš?)

Co je za hodnoty v registrech ADC? Zřejmě asi když nechce ADC hodit EOC flag, tak nekonvertuje.

Není v těchto případech nic vhodnějšího, než do debugu vlézt, otevřít registry ADC a ručně si zaklikat a zjistit, co tomu chybí.

Kód jsem prošel, vypadá v pořádku, až na pár drobností:

Nevím, co používáš za kompilátor, ale věčně jsou problémy s neinicializovanou pěmětí. Takže prosím ještě použij ADC_StructInit(&ADC_InitStruct);

(případný problém s neinicializovanou strukturou zjistíš taktéž v debugu, protože v registrech ADC bude bordel a ve struktuře taky).

Udělej nám kdyžtak prosím screenshot registrů v ADC, nějak pokudmožno čitelně (pokud to tvé IDE umí), luštit 32bitové hexa hodnoty se nikomu chtít nebude.


Potom jen taková poznámka pod čarou: Valit flouty v M0, to seš teda dobrej drak. Nezkoušej mi namluvit, že to nejde spočítat ve fixed point aritmetice. Ale já vim, lenost, že jo? Rychlost float výpočtů na CM0 si doufám uvědomuješ, stějně jako potřebnou rozsáhlost PRINTF knihovních funkcí s obsahem floutu ve FLASH. Když sem kdysi začínal na shnilých AVR, tak se ADC zvládno naškálovat několika instrukcema a vypsat na displej i bez printfu.

Mimochodem, použití sprintf je nebezpečné a ve složitějších aplikacích super díra pro hackery. Používej korektní funkci snprintf, která ti zabrání přetečení paměti.