Witam,
mam problem z poprawną konfiguracją modułu Bluetooth. Chodzi o to, że na przetwornik ADC wyzwalany timer1 podaje sygnał z GPIOB i chcę próbkować go wg ustawień timera z częstotliwością co najmniej 500Hz. Dane pobierane są z rejestru ADC przez DMA do zadeklarowanego wcześniej buforADC (unsigned short int buforADC[1]={0}
.
Teraz wg instrukcji z książki, żeby z największą prędkością przesyłać przez Bluetooth'a (19200) do buforTx (unsigned char buforTx[4]={0}
funkcją sprintf przepisuje dane z buforaADC (odpowiednio przeliczone) i wysyłam.
Niestety na terminal przychodzi znacznie mniej danych niż mogę oczekiwać (gdzieś dla częstotliwości 100Hz jeszcze wynik był satysfakcjonujący).
Nie bardzo wiem teraz gdzie tkwi problem, czy w przetworniku czy bluetooth jakoś nie nadąża i jak to zmienić.
Myślałam żeby jakoś zmienić ilość danych np.
ponieważ przetwornik jest 12bitowy na zapisanie całej liczby potrzeba w zaokrągleniu 2 bajtów i 2 bajty na znaki \r\n (stąd u mnie buforTx ma 4 elementy).
Nie wiem tylko jak zrobić, by na terminalu wyświetlały się liczby, to znaczy żeby jednak buforTx był zestawem znaków (cyfr) odczytanych wartości sygnału.
Mam nadzieję, że w miarę wyjaśniłam istotę mojego problemu. Dołączam jeszcze fragmenty kodu i proszę o wsparcie.
Pozdrawiam
USART:
void USART_Config(void)
{
//konfigurowanie ukladu USART
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 19200; //Predkosc transmisji w bps
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //Dlugosc dlowa danych
USART_InitStructure.USART_StopBits = USART_StopBits_1; //Bity stopu (1 bit)
USART_InitStructure.USART_Parity = USART_Parity_No; //Bit parzystosci (wylaczony)
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //Sprzetowa kontrola przeplywu wylaczona
USART_InitStructure.USART_Mode = USART_Mode_Tx; //Tryb pracy (nadawnie)
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);
}
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 = DISABLE; //Pomiar dwoch kanalow, konieczne skanowanie kanalow
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //Pomiar w trybie ciaglym: wylaczone
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; //Wyzwalanie zewnetrzne
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //Wyrownanie danych do prawej - 12 mlodszych bitow znaczacych
ADC_InitStructure.ADC_NbrOfChannel = 1; //Liczba uzywanych kanalow =1
ADC_Init(ADC1, &ADC_InitStructure); //Incjalizacja przetwornika
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_1Cycles5);
ADC_DMACmd(ADC1,ENABLE); //Wlaczenie DMA dla ADC1
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
}
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 = 1; //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);
}
void TIM_Config(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
//Konfiguracja licznika 1
//Ustawienia taktowania i trybu pracy licznika 1
TIM_TimeBaseStructure.TIM_Prescaler = 5600-1; //taktowanie licznka FCLK = 56MHz/5600 = 10kHz
TIM_TimeBaseStructure.TIM_Period = 100; //okres przepelnienia licznika = 20000 taktow = 0,5Hz
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //dzielnik zegara dla ukladu generacji dead-time i filtra
TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //licznik powtorzen
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //tryb pracy licznika
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //inicjalizacja licznika
//Konfiguracja kanalu 1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing; //tryb pracy kanalu
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //wlaczenie generowania sygnalu na wyjsciu licznika
TIM_OCInitStructure.TIM_Pulse =100; //40 taktow = 250Hz
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //polaryzacja wyjscia
TIM_OC1Init(TIM1, &TIM_OCInitStructure); //Inicjalizacja kanalu 1 licznika TIM1
//zapis ustawien
//Wylaczenie rejestru preload - ewentualne zmiany konfiguracji uwzgledniane sa
//od razu. Gdy preload jest wlaczony - zmiany wchodza w zycie dopiero przy
//nastepnym update
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Disable);
//Wlaczenie przerwan od licznikow
//wlaczenie przerwania od przepelnienia / aktualizacji wartości Period TIM1
TIM_ITConfig(TIM1, TIM_IT_CC1 , ENABLE);
//Wlaczenie timerow
TIM_Cmd(TIM1, ENABLE);
}
Przerwanie od USART:
extern unsigned char buforTx[];
extern unsigned char bufTxIndex;
void USART1_IRQHandler(void)
{
volatile unsigned long int i;
if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) {
USART_SendData(USART1, buforTx[bufTxIndex++]);
//for (i=0; i<5000; i++); //Odczekanie 10ms pomiedzy kolejnymi znakami komendy
if ((buforTx[bufTxIndex-2] == '\r')&&(buforTx[bufTxIndex-1] == '\n')) //Jesli wysylany zostal ostatni znak (CR)
{
USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //Wylacz przerwanie = koniec transmisji
GPIO_SetBits(GPIOB, GPIO_Pin_1);
bufTxIndex = 0;
}
}
}
mam problem z poprawną konfiguracją modułu Bluetooth. Chodzi o to, że na przetwornik ADC wyzwalany timer1 podaje sygnał z GPIOB i chcę próbkować go wg ustawień timera z częstotliwością co najmniej 500Hz. Dane pobierane są z rejestru ADC przez DMA do zadeklarowanego wcześniej buforADC (unsigned short int buforADC[1]={0}

Teraz wg instrukcji z książki, żeby z największą prędkością przesyłać przez Bluetooth'a (19200) do buforTx (unsigned char buforTx[4]={0}

Niestety na terminal przychodzi znacznie mniej danych niż mogę oczekiwać (gdzieś dla częstotliwości 100Hz jeszcze wynik był satysfakcjonujący).
Nie bardzo wiem teraz gdzie tkwi problem, czy w przetworniku czy bluetooth jakoś nie nadąża i jak to zmienić.
Myślałam żeby jakoś zmienić ilość danych np.
ponieważ przetwornik jest 12bitowy na zapisanie całej liczby potrzeba w zaokrągleniu 2 bajtów i 2 bajty na znaki \r\n (stąd u mnie buforTx ma 4 elementy).
Nie wiem tylko jak zrobić, by na terminalu wyświetlały się liczby, to znaczy żeby jednak buforTx był zestawem znaków (cyfr) odczytanych wartości sygnału.
Mam nadzieję, że w miarę wyjaśniłam istotę mojego problemu. Dołączam jeszcze fragmenty kodu i proszę o wsparcie.
Pozdrawiam
USART:
void USART_Config(void)
{
//konfigurowanie ukladu USART
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 19200; //Predkosc transmisji w bps
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //Dlugosc dlowa danych
USART_InitStructure.USART_StopBits = USART_StopBits_1; //Bity stopu (1 bit)
USART_InitStructure.USART_Parity = USART_Parity_No; //Bit parzystosci (wylaczony)
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //Sprzetowa kontrola przeplywu wylaczona
USART_InitStructure.USART_Mode = USART_Mode_Tx; //Tryb pracy (nadawnie)
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);
}
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 = DISABLE; //Pomiar dwoch kanalow, konieczne skanowanie kanalow
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //Pomiar w trybie ciaglym: wylaczone
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; //Wyzwalanie zewnetrzne
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //Wyrownanie danych do prawej - 12 mlodszych bitow znaczacych
ADC_InitStructure.ADC_NbrOfChannel = 1; //Liczba uzywanych kanalow =1
ADC_Init(ADC1, &ADC_InitStructure); //Incjalizacja przetwornika
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_1Cycles5);
ADC_DMACmd(ADC1,ENABLE); //Wlaczenie DMA dla ADC1
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
}
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 = 1; //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);
}
void TIM_Config(void) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
//Konfiguracja licznika 1
//Ustawienia taktowania i trybu pracy licznika 1
TIM_TimeBaseStructure.TIM_Prescaler = 5600-1; //taktowanie licznka FCLK = 56MHz/5600 = 10kHz
TIM_TimeBaseStructure.TIM_Period = 100; //okres przepelnienia licznika = 20000 taktow = 0,5Hz
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //dzielnik zegara dla ukladu generacji dead-time i filtra
TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //licznik powtorzen
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //tryb pracy licznika
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //inicjalizacja licznika
//Konfiguracja kanalu 1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing; //tryb pracy kanalu
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //wlaczenie generowania sygnalu na wyjsciu licznika
TIM_OCInitStructure.TIM_Pulse =100; //40 taktow = 250Hz
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //polaryzacja wyjscia
TIM_OC1Init(TIM1, &TIM_OCInitStructure); //Inicjalizacja kanalu 1 licznika TIM1
//zapis ustawien
//Wylaczenie rejestru preload - ewentualne zmiany konfiguracji uwzgledniane sa
//od razu. Gdy preload jest wlaczony - zmiany wchodza w zycie dopiero przy
//nastepnym update
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Disable);
//Wlaczenie przerwan od licznikow
//wlaczenie przerwania od przepelnienia / aktualizacji wartości Period TIM1
TIM_ITConfig(TIM1, TIM_IT_CC1 , ENABLE);
//Wlaczenie timerow
TIM_Cmd(TIM1, ENABLE);
}
Przerwanie od USART:
extern unsigned char buforTx[];
extern unsigned char bufTxIndex;
void USART1_IRQHandler(void)
{
volatile unsigned long int i;
if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) {
USART_SendData(USART1, buforTx[bufTxIndex++]);
//for (i=0; i<5000; i++); //Odczekanie 10ms pomiedzy kolejnymi znakami komendy
if ((buforTx[bufTxIndex-2] == '\r')&&(buforTx[bufTxIndex-1] == '\n')) //Jesli wysylany zostal ostatni znak (CR)
{
USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //Wylacz przerwanie = koniec transmisji
GPIO_SetBits(GPIOB, GPIO_Pin_1);
bufTxIndex = 0;
}
}
}