LinkedIn YouTube Facebook
Szukaj

Wstecz
Artykuły

[3] JAVA i STM32 – ekspresowy kurs programowania z MicroEJ – obsługa ADC i DAC

 

List. 6. Kod metody main

public static void main(String[] args) {

	DAC dac = new DAC();
	ADC adc = new ADC();
		
	dac.init();
	adc.init();
		
	MWT.RenderingContext.add(new PlainTheme());
	Desktop desktop = new Desktop();
	Panel panel = new Panel();
	GridComposite gc = new GridComposite(MWT.VERTICAL, 4);
		
	TitleLabel title = new TitleLabel("ADC/DAC EXAMPLE");
	title.setFontSize(LookExtension.GET_X_BIG_FONT_INDEX);
	gc.add(title);
	
	FlowComposite fcDac = new FlowComposite();
		
	TitleLabel labelDacTitle = new TitleLabel("Dac Value [mV]:");
	fcDac.add(labelDacTitle);
		
	TextField dacValueField = new TextField("--------");
	fcDac.add(dacValueField);
		
	Scale scaleDac = new Scale(0, 300);
	scaleDac.setListener(new DACScaleListener(dacValueField, dac));
	fcDac.add(scaleDac);
		
	gc.add(fcDac);

	FlowComposite fcAdc = new FlowComposite();
		
	TitleLabel labelAdcTitle = new TitleLabel("ADC Value [mV]:");
	fcAdc.add(labelAdcTitle);
		
	TextField adcValueField = new TextField("--------");
	fcAdc.add(adcValueField);
		
	Button buttonAdc = new Button("Get ADC value");
	buttonAdc.setListener(new ADCButtonListener(adcValueField, adc));
	fcAdc.add(buttonAdc);

	gc.add(fcAdc);
		
	panel.setWidget(gc);
	panel.show(desktop, true);
	desktop.show();
}
 

Wystarczy już tylko utworzyć nową konfiguracją z opcją Execute on EmbJPF, aby aplikacja była gotowa do zaprogramowania w pamięci mikrokontrolera.

Obsługa przetworników (C)

Przed uruchomieniem aplikacji trzeba jeszcze dokonać zmian w BSC dodając obsługę przetworników. Po uruchomieniu projektu w środowisku uVision należy utworzyć dwa nowe pliki adc.c i dac.c zawierające implementacje zadeklarowanych w Javie funkcji kontroli przetworników. Funkcje te pokazano na listingach 7 i 8.

List. 7. Implementacja funkcji inicjalizacji i pobrania wartości przetwornika analogowo-cyfrowego

void Java_app_ADC_ADCInit(void) {
	
	printf("ADC init\n");
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  ADC_CommonInitTypeDef ADC_CommonInitStructure;
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
  ADC_CommonInit(&ADC_CommonInitStructure);

  ADC_InitTypeDef ADC_InitStructure;
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;
  ADC_InitStructure.ADC_NbrOfConversion = 1;
  ADC_Init(ADC3, &ADC_InitStructure);

  ADC_RegularChannelConfig(ADC3, ADC_Channel_13, 1, ADC_SampleTime_3Cycles);
  ADC_Cmd(ADC3, ENABLE);	
}

int Java_app_ADC_ADCGetValue(void) {
	
	printf("ADC get value\n");
	
	ADC_SoftwareStartConv(ADC3);
	
	while(ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC) == RESET)
		__NOP();
	
	ADC_ClearFlag(ADC3, ADC_FLAG_EOC);
	
	uint32_t data = ADC_GetConversionValue(ADC3) >> 4;
	data = data * 3000/4096;
	
	return (int)data;
} 

List. 8. Implementacja funkcji inicjalizacji i ustawiania wartości przetwornika cyfrowo-analogowego

void Java_app_DAC_DACInit(void) {
	
	printf("DAC init\n");
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin		= GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Speed 	= GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_AN;
	GPIO_InitStructure.GPIO_PuPd	= GPIO_PuPd_NOPULL;

	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	DAC_InitTypeDef  DAC_InitStructure;
	DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
  DAC_Init(DAC_Channel_2, &DAC_InitStructure);
	DAC_Cmd(DAC_Channel_2, ENABLE);
	
	DAC_SetChannel2Data(DAC_Align_12b_L, 0x0);
}

void Java_app_DAC_DACSetValue(int value) {
	printf("DAC set value %d\n", value);
	
	uint32_t data = value * 4095 / 3000;
	
	DAC_SetChannel2Data(DAC_Align_12b_R, (uint16_t)data);
}
  

Na pierwszy rzut oka można zauważyć charakterystyczne nazwy wszystkich czterech funkcji. Z uwagi na to, że są one wywoływane z kodu Javy, muszą one mieć w swojej nazwie pełną ścieżkę do swoich deklaracji w aplikacji z uwzględnieniem pakietów i klas w których się one znajdują. Poza nazwani, nie odbiegają niczym od funkcji znanych z przykładów biblioteki STM32 Standard Peripheral Library. Funkcje konfiguracyjne inicjalizują sygnały zegarowe dla swoich peryferii oraz przypisanych im portów GPIO (PC3 dla ADC i PA5 dla DAC) wypełniają struktury inicjalizacyjne. Funkcja odczytująca wartość ADC nie wykorzystuje przerwań, lecz po uruchomieniu konwersji czeka na jej zakończenie sygnalizowane odpowiednią flagą.

Projekt można teraz skompilować i zaprogramować pamięć mikrokontrolera. Po każdym odwołaniu do funkcji C, w konsoli debugowania (Debug (printf) Viewer) można zaobserwować logi wyświetlane przez poszczególne funkcje.