Odczytując dane z przetwornika AC należy zapisać je najlepiej do tablicy o ilości elementów równej ilości przetworników AC, następnie zamienić je na dane typu string poprzez rzutowanie.
Dane te możemy wtedy wpisać do portu USART który to wyśle je nam na komputer poprzez złącze RS232 lub bluuthu podłączonego do tego portu.
Oto przykład takiego rozwiązania nie piszę całego kodu tylko ważniejsze szczegóły, podczas pisania używam standardowych bibliotek STM32F10x_StdPeriph_Lib_V3.3.0
Tworzenie tablicy
unsigned char buforTx[50]={0}; // tablica do wysyłania poprzez usart
unsigned short int buforADC[8]={0}; // tablica do zapisu danych z przetwornika AC
unsigned char buforRx[17]={0}; // tablia odbioru opcjonalnie
unsigned char bufRxIndex=0;
unsigned char bufTxIndex=0;
bool odebranoDane=FALSE;
unsigned int a = 0;
podprogram odczytu danych z przetworników AC
void ADC_Config(void)
{
//konfigurowanie przetwornika AC
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //Jeden przetwornik, praca niezalezna
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //Pomiar dwoch kanalow, konieczne skanowanie kanalow
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //Pomiar w trybie ciaglym
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //Brak wyzwalania zewnetrznego
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //Wyrownanie danych do prawej - 12 mlodszych bitow znaczacych
ADC_InitStructure.ADC_NbrOfChannel = 8; //Liczba uzywanych kanalow =2
ADC_Init(ADC1, &ADC_InitStructure); //Incjalizacja przetwornika
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_13Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_13Cycles5); //Kanal 14 - GPIOC4 - potencjometr na plytce ZL27ARM
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_13Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_13Cycles5); //Kanal 16 - wewnetrzny czujnik temp. procesora
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 5, ADC_SampleTime_13Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 6, ADC_SampleTime_13Cycles5); //Kanal 14 - GPIOC4 - potencjometr na plytce ZL27ARM
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 7, ADC_SampleTime_13Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 8, ADC_SampleTime_13Cycles5); //239,5 => 17.1us = czas zalecany w dokumentacji MUC dla miernika temperatury
ADC_TempSensorVrefintCmd(ENABLE); //Wlaczenie czujnika temperatury procesora
ADC_DMACmd(ADC1,ENABLE); //Wlaczenie DMA dla ADC
ADC_Cmd(ADC1, ENABLE); //Wlacz ADC1
ADC_ResetCalibration(ADC1); //Reset rejestrow kalibracyjnych ADC1
while(ADC_GetResetCalibrationStatus(ADC1)); //Odczekanie na wykonanie resetu
ADC_StartCalibration(ADC1); //Kalibracja ADC1
while(ADC_GetCalibrationStatus(ADC1)); //Odczekanie na zakonczenie kalibracji ADC1
}
By zapisać dane do tablicy należy jeszcze skonfigurować kanał DMA
void DMA_Config(void)
{
//konfigurowanie DMA
#define ADC1_DR_Address 0x4001244C; //adres rejestru ADC1->DR
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel1); //Usun ewentualna poprzednia konfiguracje DMA
DMA_InitStructure.DMA_PeripheralBaseAddr = (unsigned long int)ADC1_DR_Address; //Adres docelowy transferu
DMA_InitStructure.DMA_MemoryBaseAddr = (unsigned long int)&buforADC; //Adres poczatku bloku do przeslania
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //Kierunek transferu
DMA_InitStructure.DMA_BufferSize = 8; //Liczba elementow do przeslania (dlugosc bufora)
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //Wylaczenie automatycznego zwiekszania adresu po stronie ADC
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //Wlaczenie automatycznego zwiekszania adresu po stronie pamieci (bufora)
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //Rozmiar pojedynczych przesylanych danych po stronie ADC (HalfWord = 16bit)
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //Rozmiar pojedynczych przesylanych danych po stronie pamieci (bufora)
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //Tryb dzialania kontrolera DMA - powtarzanie cykliczne
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //Priorytet DMA - wysoki
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //Wylaczenie obslugi transferu z pamieci do pamieci
DMA_Init(DMA1_Channel1, &DMA_InitStructure); //Zapis konfiguracji
//Wlacz DMA, kanal 1
DMA_Cmd(DMA1_Channel1, ENABLE);
}
Należy skonfigurować układ przerwań dla transferu danych pomiędzy przetwornikami i pamięcią oraz portem wyjściowym USART
void NVIC_Config(void)
{
//Konfigurowanie kontrolera przerwan NVIC
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
// Jezeli tablica wektorow w RAM, to ustaw jej adres na 0x20000000
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else // VECT_TAB_FLASH
// W przeciwnym wypadku ustaw na 0x08000000
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//Wlacz przerwanie od ADC
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//Przerwanie od USART1
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
Ostatnie ustawienia to port komunikacji USART
void USART_Config(void)
{
//konfigurowanie ukladu USART
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 19200; //Predkosc transmisji =19200bps
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //Dlugosc slowa = 8 bitow
USART_InitStructure.USART_StopBits = USART_StopBits_1; //1 bit stopu
USART_InitStructure.USART_Parity = USART_Parity_No; //Brak kontroli parzystosci
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //Kontrola przeplywu danych (brak)
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //Tryb pracy
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
Pozostaje nam jeszcze ustawić przerwanie w pliku biblioteki stm32f10x_it.c w linijce około 580 void USART1_IRQHandler(void)
Treść danych
extern unsigned char buforRx[];
extern unsigned char bufRxIndex;
extern unsigned char buforTx[];
extern unsigned char bufTxIndex;
extern bool odebranoDane;
extern unsigned int a;
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
buforRx[bufRxIndex] = USART_ReceiveData(USART1); //Odczyt danej automatycznie kasuje flage przerwania
if(buforRx[bufRxIndex] == 0x0D) //Wykrycie znaku \CR
{
odebranoDane = TRUE;
while (bufRxIndex<17) { //wyzerowanie znakow do konca bufora (zabezpiecza przed wyswietlaniem "smieci")
buforRx[bufRxIndex]=0;
bufRxIndex++;
}
bufRxIndex = 0;
} else { //Obsluga pozostalych, "zwyklych" znakow
bufRxIndex++;
if (bufRxIndex>16){ //Zabezpieczenie przed przepelnieniem bufora jesli odbierany tekst jest dluzszy niz 16 znakow
bufRxIndex=0;
} } }
if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) {
USART_SendData(USART1, buforTx[bufTxIndex++]); //Wyslij kolejny znak i zwieksz indeks bufora wyjsciowego
if(buforTx[bufTxIndex-1] == 0x0D) //Jesli wysylany zostal ostatni znak (CR)
{
USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //Wylacz przerwanie = koniec transmisji
bufTxIndex = 0;
a++;
} } }
Pozwala to na transmisję danych w przerwaniu co odciąża procesor od pracy
Oto główna część kodu programu zapewniająca prawidłową transmisję danych
int main(void)
{
RCC_Config();
GPIO_Config();
NVIC_Config();
DMA_Config();
ADC_Config();
USART_Config();
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //rozpocznij przetwarzanie AC
while (1) {
for (i=0;i<1000000;i++)
if(a>500){a=0;}
sprintf((char*)buforTx," %04i %04i %04i %04i %04i %04i %04i %04i %04i %1c",a,buforADC[0],buforADC[1],buforADC[2],buforADC[3],buforADC[4],buforADC[5],buforADC[6],buforADC[7],0x01);
// zamiana danych z int na char poprzez rzutowanie co pozwala wyświetlać dane na komputerze bezpośrednio po odebraniu.
buforTx[49]=0X0D; //Dodanie znacznika nowej linii (i konca transmisji)
USART_ITConfig(USART1, USART_IT_TXE, ENABLE); //Wlacz przerwanie = rozpocznij transmisjie
}; }
W razie problemów lub gdy czegoś nie można zrozumieć pomogę w miarę możliwości
Mój adres zbigniew.kolb@gmail.com