STM32 pomoc w zrozumieniu przerwań

Język C dla mikrokontrolerów ARM
ODPOWIEDZ
mateusz19955
Użytkownik
Posty: 5
Rejestracja: 27 sty 2019, 14:57

STM32 pomoc w zrozumieniu przerwań

Post autor: mateusz19955 » 27 sty 2019, 15:20

Witam,
Od kilku dni uczę się programowania mikro kontrolerów STM32 a dokładnie STM32F103VBT6 zestaw ZL27ARM.
Środowisko w jakim programuję to System Workbench for STM32 działa na Eclipse.
Mam takie małe pytanie dotyczące przerwań (modułu NVIC), bo są tam modele grupowań, priorytety grupowe i podpriorytety.
Załóżmy że wybrałem sobie model grupowania NVIC_PriorityGroup_1 i są tam dostępne dwa priorytety grupowe i osiem podpriorytetów.
Czyli jest to po cztery podpriorytety dla każdego priorytetu grupowego czy po osiem?

Czy dobrze to napisałem:
  1. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);                // model grupowania NVIC_PriorityGroup_1
  2.  
  3. nvic.NVIC_IRQChannel = EXTI0_IRQn;                  // źrodło przerwania
  4. nvic.NVIC_IRQChannelPreemptionPriority = 0;             // priorytet grupowy przerwania
  5. nvic.NVIC_IRQChannelSubPriority = 0;                        // podpriorytet przerwania
  6. nvic.NVIC_IRQChannelCmd = ENABLE;                   // włącz dane źródło przerwania
  7. NVIC_Init(&nvic);
  8.  
  9. nvic.NVIC_IRQChannel = EXTI1_IRQn;                  // źrodło przerwania
  10. nvic.NVIC_IRQChannelPreemptionPriority = 1;             // priorytet grupowy przerwania
  11. nvic.NVIC_IRQChannelSubPriority = 0;                        // podpriorytet przerwania
  12. nvic.NVIC_IRQChannelCmd = ENABLE;                   // włącz dane źródło przerwania
  13. NVIC_Init(&nvic);
Według tego ustawienia pierwszeństwo w wykonaniu będzie miało EXTI0_IRQn bo ma priorytet grupowy 0.

squeez
Użytkownik
Posty: 130
Rejestracja: 16 paź 2017, 23:52

Re: STM32 pomoc w zrozumieniu przerwań

Post autor: squeez » 27 sty 2019, 20:09

z tego co ja rozumie (a mogę się mylić) łącznie do wykorzystania jest niejako 16 szufladek do wykorzystania na priorytetowanie, że się tak wyrażę.

I teraz jeśli jest 1 grupa wówczas wszystkie przerwania należą do jednej grupy ale możesz przypisać 16 podgrup.
Jeśli zrobisz 2 grupy to dla każdej z nich będziesz miał do wykorzystania 8 podgrup. przy czym przerwania z grupy o wyższym priorytecie będą obsłużone w pierwszej kolejności, ewentulanie możliwość wywłaszczenia przerwania o niższym priorytecie (grupiy) w ramach jednej grupy masz jeszcze podział na 8 podgrup.

16/2 = 8 jak zrobisz 4 grupy to w każdej grupie będziesz miał możliwość 4 podgrup 16/4=4 i tak dalej potem 8 grup po 2 podgrupy i 16 grup z 1 podgrupą.

Wyższy priorytet mają te z mniejszą liczbą 0 - to najwyższy priorytet. Nie wczytywał się w przykład bo w HAL-u nie piszę a na STM32 też za dużo nie pisałem raczej dla treningu.

Ale wygląda tak jak piszesz EXTI0 ma grupe 0 EXTI1 w grupie 1 czyli grupa 0 (EXT0) ma wyższy priorytet i będzie obsłużone przed EXTI1 chyba nawet priorytet grupowy może wywłaszczyć niższy priorytet grupowy, nie pamiętam czy jest to domyślne zachowanie czy do ustawienia, bo w ramach tej samej grupy wywłaszczeń chyba nie ma tylko pierwszeństwo obsłużenia ... ale tu mogę się mylić.
Pewnie z ciekawości sam sprawdzę to w RM :)

Dodano po 25 minutach 30 sekundach:
No dobra okłamałem cię że to w RM chyba bardziej w PM bo NVIC to część rdzenia dostarczana przez ARM a dokumentacja techniczna (RM) to opis peryferii (dostawcy krzemu). w PM jest rozdział 2.3.6 Interrupt priority grouping
I z tego co czytam to grupy o wyższym priorytecie może wywłaszczyć przerwanie z grupy o niższym. W ramach tej samej grupy nie.

Awatar użytkownika
SunRiver
Administrator
Posty: 772
Rejestracja: 08 paź 2017, 11:27
Lokalizacja: Opole
Kontakt:

Re: STM32 pomoc w zrozumieniu przerwań

Post autor: SunRiver » 27 sty 2019, 20:36

zasadniczo przerwania są proste do ogarnięcia w STM32

Weźmy np przerwania GPIO , gdzie ze względu na ilość GPIO pogrupowano wektory przerwań od GPIO dość logicznie :
EXTI0 - to przerwanie od wszystkich pinów GPIO 0 (zero) w każdym porcie
EXTI1 - wszystkie linie 1 .... i można by napisać itd ... ale
Linie GPIO 5 do 9 wszystkich portów wywołują przerwanie EXTI9_5 a pozostałe EXTI15_10 ....

Inna sprawa jest taka , że zarówno kontroler przerwań NVIC jak weźmy wszechobecny SYSTIK są dostarczane przez RDZEŃ
a peryferia jak GPIO czy UART, CAN itd są zalezne od producenta krzemu (STM, ATMEL, itd ...)
dlatego powinieneś się w zasadzie skupić na dokumentach od ARM , bardziej niż RM od STMa ...

http://infocenter.arm.com/help/index.js ... index.html

bo w zasadzie chodzi o to że ułatwiono życie zarówno nam programistom jak i producentom mikrokontrolerów gdzie
przypisano przerwania , do których producent dopina swoje peryferia , a dla nas nie zmienia się to niezależnie od producenta
przez co pod konkretnym numerem przerwania jest konkretny sprzęt i nieważne jak go producent wykona będzie działać.
i tu mamy ciekawostkę czyli rejestry przerwań ogólnych oraz systick :)

Systik zatem są zawsze gwarantowany w rdzeniu ... i teraz wiesz że to są cechy wspólne wszystkich arm niezależnie od producenta
a że szkoda zasobów na to żeby aktywować przerwania IRQ1-255 dostał specjalny bit w osobnym rejestrze NVIC chodzi oczywiście
o bit control ... dlaczego ?? no sam powiedz czy nie szkoda przestrzeni na jeden bit w 32bit rejestrach ?? szkoda marnować ...bo
oczywiste jest ze przecież systic i tak tam będzie .. co innego uart , adc czy inne peryferium które może nie zostać zaimplementopwane.
do tego jeszcze Systick ma ustawienia priorytetu , co ładnie widać tutaj : http://infocenter.arm.com/help/index.js ... cfdhi.html ... kolejny ciekawy przypadek External Interrupt to są przerwania poza rdzeniem ....

I tu jest ładnie w CMSIS wszystko pozbierane żeby było łatwiej programistom :)
Dlatego też podstawą pakietu dla Cortex od ARM jest: rdzeń, magistrale, NVIC, SysTick, DWT , ITM.
zaś cała reszta czyli RCC, UART, I2C, SPI, CAN, ETH, USB, GPIO są zależne od wytwórcy krzemu,
i przerwania od tych peryferii są tylko mapowane pod IRQx w NVIC.

Nie wyczerpuje to odpowiedzi na twoje pytanie , ale pokazuje zależności bo zakładam że w dokument rzeczony od ARM
kolega się nie zagłebiał a wszystko ładnie jest opisane np tu: http://infocenter.arm.com/help/index.js ... 03s02.html

Jak widać ustawienia priorytetów grupowych i pdgrupowych wymaga ustawienia odpowiednich trybów zapisanych do rejestru Application Interrupt and Reset Control Register na pozycji bitów PRIGROUP. dzięki czemu zostaną prawidłowo zinterpretowane pola IP rejestru Interrupt Priority Registers. Jka wiec już czytasz to widzisz że zawartość tego pola to jeden bajt wiec siłą rzeczy dla jednego rejestru są to 4 pola,
które odpowiadają za swój numer IRQ -- i tu uwaga pierwszy rejestr IP zawiera w sobie info dotyczące
priorytetów dla IRQ0 - 3 ...

Reszta we wskazanym dokumencie który powinien być przy cortexach podstawową lekturą :) oraz w ERRATACH ... bo jest wiele dziwnych niuansów ...

Dodano po 20 minutach 14 sekundach:
ale reasumując ...w pigułce ...:P
W M3 masz dwa główne rodzaje przerwań :

- przerwania systemowe
- przerwania zewnętrzne

wiec za priorytet odpowiada 4 bity rejestru , łacznie masz do dyspozycji 16 poziomów priorytetów, mozesz ustalić ile bitów odpowiada za PG a ile za SP wewnątrz grupy w symie masz dostępne 5 opcji podziału priorytetów na GROUP i SUB. To zostanie zapisane w kolejnych 4 bitach. A róznice w priorytetach wynikają z faktu iż jeśli wykonuje się przerwanie , a wystąpi inne o wyższym priorytecie to wystąpi wywłaszczenie, zaś jeśli wystąpi inne przerwanie o takim samym grypowym ale innym podrzędnym priorytecie ... to wywłaszczenia nie będzie . Oczywiście moze byc tez sytuacja że 2 przerwania bedą oczekiwać na rdzen (bo ten akurat wymiotuje w ważniejszym przerwaniu) to nastąpi procedura arbitrażu i pierwszeństwo będzie miało to przerwanie które ma wyższy priorytet podrzędny .....


trochę to pomieszane , ale tak naprawdę jest proste i łatwe do ogarnięcia :)
.... z każdym bitem serca ....
💫SunDUINO
💦GitHUB
💦Google Drive
💦Sotton

mateusz19955
Użytkownik
Posty: 5
Rejestracja: 27 sty 2019, 14:57

Re: STM32 pomoc w zrozumieniu przerwań

Post autor: mateusz19955 » 28 sty 2019, 17:16

Witam,
Ogarnąłem już te priorytety i pod priorytety (przynajmniej tak mi się wydaje) ale mam teraz inny problem.
Ćwiczę sobie przerwania od EXTI i czytałem że wszystkie piny GPIO_Pin_0 każdego portu wywołują jedno przerwanie, i dopiero w tym przerwaniu trzeba odróżnić z którego konkretnie pinu(portu) to przyszło.
No i napisałem sobie program który ma mi to realizować ale nie działa tak jak chciałem.
Według tego co napisałem to przerwanie void EXTI0_IRQHandler() powinno być wywoływane pinem 0 portu A i C, a wywołuje go tylko port C.
To drugie przerwanie działa tak jak powinno.
Dlaczego tak się dzieje?

Oto mój kod:
  1. #include "stm32f10x.h"
  2.  
  3. void nvicConfig(void);
  4. void extiConfig(void);
  5. void gpioConfig(void);
  6. void delay(int time);
  7.  
  8. int main(void){
  9.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  10.  
  11.     gpioConfig();
  12.     extiConfig();
  13.     nvicConfig();
  14.  
  15.     while(1);
  16. }
  17.  
  18. void nvicConfig(void){
  19.     NVIC_InitTypeDef nvic;
  20.  
  21.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  22.  
  23.     nvic.NVIC_IRQChannel = EXTI0_IRQn;
  24.     nvic.NVIC_IRQChannelPreemptionPriority = 1;
  25.     nvic.NVIC_IRQChannelSubPriority = 0x00;
  26.     nvic.NVIC_IRQChannelCmd = ENABLE;
  27.     NVIC_Init(&nvic);
  28.  
  29.     nvic.NVIC_IRQChannel = EXTI15_10_IRQn;
  30.     nvic.NVIC_IRQChannelPreemptionPriority = 2;
  31.     nvic.NVIC_IRQChannelSubPriority = 0x00;
  32.     nvic.NVIC_IRQChannelCmd = ENABLE;
  33.     NVIC_Init(&nvic);
  34. }
  35.  
  36. void extiConfig(void){
  37.     EXTI_InitTypeDef exti;
  38.  
  39.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
  40.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource0);
  41.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource10);
  42.  
  43.     EXTI_StructInit(&exti);
  44.     exti.EXTI_Line = EXTI_Line0;
  45.     exti.EXTI_Mode = EXTI_Mode_Interrupt;
  46.     exti.EXTI_Trigger = EXTI_Trigger_Falling;
  47.     exti.EXTI_LineCmd = ENABLE;
  48.     EXTI_Init(&exti);
  49.  
  50.     EXTI_StructInit(&exti);
  51.     exti.EXTI_Line = EXTI_Line10;
  52.     exti.EXTI_Mode = EXTI_Mode_Interrupt;
  53.     exti.EXTI_Trigger = EXTI_Trigger_Falling;
  54.     exti.EXTI_LineCmd = ENABLE;
  55.     EXTI_Init(&exti);
  56. }
  57.  
  58. void gpioConfig(void){
  59.     GPIO_InitTypeDef gpio;
  60.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, ENABLE);
  61.  
  62.     GPIO_StructInit(&gpio);
  63.     gpio.GPIO_Pin = GPIO_Pin_All;
  64.     gpio.GPIO_Mode = GPIO_Mode_Out_PP;
  65.     GPIO_Init(GPIOB, &gpio);
  66.  
  67.     GPIO_StructInit(&gpio);
  68.     gpio.GPIO_Pin = GPIO_Pin_0;
  69.     gpio.GPIO_Mode = GPIO_Mode_IPU;
  70.     GPIO_Init(GPIOA, &gpio);
  71.  
  72.     GPIO_StructInit(&gpio);
  73.     gpio.GPIO_Pin = GPIO_Pin_0;
  74.     gpio.GPIO_Mode = GPIO_Mode_IPU;
  75.     GPIO_Init(GPIOC, &gpio);
  76.  
  77.     GPIO_StructInit(&gpio);
  78.     gpio.GPIO_Pin = GPIO_Pin_10;
  79.     gpio.GPIO_Mode = GPIO_Mode_IPU;
  80.     GPIO_Init(GPIOD, &gpio);
  81. }
  82.  
  83. void delay(int time){
  84.     int i;
  85.     for (i = 0; i < time * 4000; i++) {}
  86. }
  87.  
  88. void EXTI15_10_IRQHandler(){
  89.     if (EXTI_GetITStatus(EXTI_Line10)) {
  90.         if (GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_10) == 0) { // jesli przycisk jest przycisniety
  91.             GPIO_SetBits(GPIOB, GPIO_Pin_8); // zapal diode
  92.             delay(2000);
  93.             GPIO_ResetBits(GPIOB, GPIO_Pin_8);
  94.         }
  95.  
  96.         EXTI_ClearITPendingBit(EXTI_Line10);
  97.     }
  98. }
  99.  
  100. void EXTI0_IRQHandler(){
  101.     if (EXTI_GetITStatus(EXTI_Line0)) {
  102.         if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0) { // jesli przycisk jest przycisniety
  103.             GPIO_SetBits(GPIOB, GPIO_Pin_15); // zapal diode
  104.             delay(2000);
  105.             GPIO_ResetBits(GPIOB, GPIO_Pin_15);
  106.         }
  107.  
  108.         if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0) { // jesli przycisk jest przycisniety
  109.             GPIO_SetBits(GPIOB, GPIO_Pin_13); // zapal diode
  110.             delay(2000);
  111.             GPIO_ResetBits(GPIOB, GPIO_Pin_13);
  112.         }
  113.  
  114.         EXTI_ClearITPendingBit(EXTI_Line0);
  115.     }
  116. }
Te opóźnienia delay(2000) w tych wektorach przerwań dałem tylko po to aby zobaczyć jak działają te priorytety.
Wiem że ich tam nie powino być

mateusz19955
Użytkownik
Posty: 5
Rejestracja: 27 sty 2019, 14:57

Re: STM32 pomoc w zrozumieniu przerwań

Post autor: mateusz19955 » 30 sty 2019, 19:38

Witam,
To jak, pomoże mi ktoś z tymi EXTI?
Teraz napisałem program do likwidacji drgań styków w switch-ach, i chciałem sobie zrobić aby exti reagowało na pin PA0 i PC0.
Ale nie działa reaguje tylko na PC0.
Co piszę źle, przecież wszystkie piny 0 do 4 każdego portu wywołują to samo przerwanie?
Tzn. wszystkie piny 0 portu A,B,C,D,E to jedno przerwanie a wszystkie piny 1 portu A,B,C,D,E to drugie przerwanie, itd.

Oto kod:
  1. #include "stm32f10x.h"
  2.  
  3. void gpioConfig(void);
  4. void nvicConfig(void);
  5. void extiConfig(void);
  6. void timerConfig(void);
  7.  
  8. int main(void){
  9.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);
  10.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  11.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  12.  
  13.     gpioConfig();
  14.     nvicConfig();
  15.     extiConfig();
  16.     timerConfig();
  17.  
  18.     for(;;);
  19. }
  20.  
  21. void gpioConfig(void){
  22.     GPIO_InitTypeDef    gpio;
  23.  
  24.     GPIO_StructInit(&gpio);
  25.     gpio.GPIO_Pin = GPIO_Pin_All;
  26.     gpio.GPIO_Mode = GPIO_Mode_IPU;
  27.     GPIO_Init(GPIOA, &gpio);
  28.  
  29.     GPIO_StructInit(&gpio);
  30.     gpio.GPIO_Pin = GPIO_Pin_All;
  31.     gpio.GPIO_Mode = GPIO_Mode_Out_PP;
  32.     GPIO_Init(GPIOB, &gpio);
  33.  
  34.     GPIO_StructInit(&gpio);
  35.     gpio.GPIO_Pin = GPIO_Pin_All;
  36.     gpio.GPIO_Mode = GPIO_Mode_IPU;
  37.     GPIO_Init(GPIOC, &gpio);
  38. }
  39.  
  40. void nvicConfig(void){
  41.     NVIC_InitTypeDef    nvic;
  42.  
  43.     nvic.NVIC_IRQChannel = TIM2_IRQn;
  44.     nvic.NVIC_IRQChannelPreemptionPriority = 0;
  45.     nvic.NVIC_IRQChannelSubPriority = 0;
  46.     nvic.NVIC_IRQChannelCmd = ENABLE;
  47.     NVIC_Init(&nvic);
  48.  
  49.     nvic.NVIC_IRQChannel = EXTI0_IRQn;
  50.     nvic.NVIC_IRQChannelPreemptionPriority = 0;
  51.     nvic.NVIC_IRQChannelSubPriority = 0;
  52.     nvic.NVIC_IRQChannelCmd = ENABLE;
  53.     NVIC_Init(&nvic);
  54.  
  55.     nvic.NVIC_IRQChannel = EXTI1_IRQn;
  56.     nvic.NVIC_IRQChannelPreemptionPriority = 0;
  57.     nvic.NVIC_IRQChannelSubPriority = 0;
  58.     nvic.NVIC_IRQChannelCmd = ENABLE;
  59.     NVIC_Init(&nvic);
  60. }
  61.  
  62. void extiConfig(void){
  63.     EXTI_InitTypeDef    exti;
  64.  
  65.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
  66.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource0);
  67.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
  68.  
  69.     EXTI_StructInit(&exti);
  70.     exti.EXTI_Line = EXTI_Line0;
  71.     exti.EXTI_Mode = EXTI_Mode_Interrupt;
  72.     exti.EXTI_Trigger = EXTI_Trigger_Falling;
  73.     exti.EXTI_LineCmd = ENABLE;
  74.     EXTI_Init(&exti);
  75.  
  76.     EXTI_StructInit(&exti);
  77.     exti.EXTI_Line = EXTI_Line1;
  78.     exti.EXTI_Mode = EXTI_Mode_Interrupt;
  79.     exti.EXTI_Trigger = EXTI_Trigger_Falling;
  80.     exti.EXTI_LineCmd = ENABLE;
  81.     EXTI_Init(&exti);
  82. }
  83.  
  84. void timerConfig(void){
  85.     TIM_TimeBaseInitTypeDef     tim;
  86.  
  87.     tim.TIM_Prescaler = 7199;
  88.     tim.TIM_Period = 1500;
  89.     tim.TIM_ClockDivision = TIM_CKD_DIV1;
  90.     tim.TIM_CounterMode = TIM_CounterMode_Up;
  91.     TIM_TimeBaseInit(TIM2, &tim);
  92. }
  93.  
  94. void EXTI0_IRQHandler(void){
  95.     if(EXTI_GetITStatus(EXTI_Line0)){
  96.         TIM_SetCounter(TIM2, 0);                    // zerowanie licznika
  97.         TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);  // włącz przerwanie TIM2
  98.         TIM_Cmd(TIM2, ENABLE);                      // włącz licznik TIM2
  99.  
  100.         EXTI_ClearITPendingBit(EXTI_Line0);
  101.     }
  102. }
  103.  
  104. void EXTI1_IRQHandler(void){
  105.     if(EXTI_GetITStatus(EXTI_Line1)){
  106.         TIM_SetCounter(TIM2, 0);                    // zerowanie licznika
  107.         TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);  // włącz przerwanie TIM2
  108.         TIM_Cmd(TIM2, ENABLE);                      // włącz licznik TIM2
  109.  
  110.         EXTI_ClearITPendingBit(EXTI_Line1);
  111.     }
  112. }
  113.  
  114. void TIM2_IRQHandler(void){
  115.     if(TIM_GetITStatus(TIM2, TIM_IT_Update)!=RESET){
  116.         TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  117.  
  118.         TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
  119.         TIM_Cmd(TIM2, DISABLE);
  120.  
  121.         if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)==0){
  122.             GPIO_WriteBit(GPIOB, GPIO_Pin_12, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_12)));
  123.         }
  124.  
  125.         if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)==0){
  126.             GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_8)));
  127.         }
  128.  
  129.         if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0)==0){
  130.             GPIO_WriteBit(GPIOB, GPIO_Pin_15, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_15)));
  131.         }
  132.     }
  133. }

Awatar użytkownika
SunRiver
Administrator
Posty: 772
Rejestracja: 08 paź 2017, 11:27
Lokalizacja: Opole
Kontakt:

Re: STM32 pomoc w zrozumieniu przerwań

Post autor: SunRiver » 30 sty 2019, 20:52

oczywiście wiesz że przycisków nie obsługuje się przez EXTI a w przerwaniu Timera , tą drogą trochę się prosisz o takie kłopoty , mozna to zrealizować
ale nie jest to zdrowe :)
.... z każdym bitem serca ....
💫SunDUINO
💦GitHUB
💦Google Drive
💦Sotton

mateusz19955
Użytkownik
Posty: 5
Rejestracja: 27 sty 2019, 14:57

Re: STM32 pomoc w zrozumieniu przerwań

Post autor: mateusz19955 » 30 sty 2019, 20:59

To znaczy, że do EXTI nie można podpinać przycisków?

Awatar użytkownika
SunRiver
Administrator
Posty: 772
Rejestracja: 08 paź 2017, 11:27
Lokalizacja: Opole
Kontakt:

Re: STM32 pomoc w zrozumieniu przerwań

Post autor: SunRiver » 30 sty 2019, 21:03

spowodowane jest to tym że prawdopodobnie źle zinterpretowałeś działanie przerwań :)

oczywiście do EXTI0 są przypisane wszystkie piny 0 czyli PA0, PB0, PC0 ..... ale jest jeden mały kłopot opisany zresztą w dokumecie
któy przytaczałem , chodzi o to że na raz może być aktywne w danej linii tylko jedno źródło przerwania
Dlatego możesz zdecydować który pin ma je wywoływać ale może być to tylko 1 pin :) np PC0 lub PF0 ... ale nie mogą być dwa :)
Dlatego też pewnie cię zastanawiało skąd procek wie który pin aktywował przerwanie ... no właśnie nie wie dlatego nie możesz ustawić 2ch
pinów 0 na przerwaniu :) , za to możesz wybrac który będzie to robił w jednym z rejestrów AFIO_EXTICRx ....

dlatego się ustawia piny na przerwaniu Timera , ew .... mozesz używać EXTI , ale przyciski na róznych liniach np:

EXTI0 -- PB0
EXTI1 -- PB1
EXTI2 -- PC2
EXTI3 -- PF3

Mam nadzieję że teraz to jasne jest i już wiesz czemu ci nie działa kod :)
Jak tez wspomniałem .... szkoda EXTI na batony :)

Dodano po 5 minutach 28 sekundach:
inaczej mówiąc EXTI używasz do przerwań ważniejszych np przerwanie od czujnika ciśnienia , przerwanie od magnetometru itd...
Przyciski wszystkie możesz zdefiniować w przerwaniu timera łatwiej bo tam tylko sprawdzasz czy został naciśniety zależnie od wyboru
czy LOW czy HIGH i dla danego przycisku jęsli np LOW definiujesz co ma się wydarzyć .... :)

mam nadzieję że teraz jest to jasne :)
.... z każdym bitem serca ....
💫SunDUINO
💦GitHUB
💦Google Drive
💦Sotton

mateusz19955
Użytkownik
Posty: 5
Rejestracja: 27 sty 2019, 14:57

Re: STM32 pomoc w zrozumieniu przerwań

Post autor: mateusz19955 » 31 sty 2019, 19:56

Kod do DMA:
  1. #include "stm32f10x.h"
  2.            
  3. void timerConfig(void);
  4. void gpioConfig(void);
  5. void nvicConfig(void);
  6. void dmaConfig(void);
  7.  
  8. uint8_t wypelnieniePWM = 10;
  9.  
  10. int main(void){
  11.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
  12.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  13.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  14.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  15.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  16.  
  17.     gpioConfig();
  18.     nvicConfig();
  19.     timerConfig();
  20.     dmaConfig();
  21.  
  22.     while(1){
  23.        
  24.     }
  25. }
  26.  
  27. void gpioConfig(void){
  28.     GPIO_InitTypeDef    gpio;
  29.  
  30.     GPIO_StructInit(&gpio);
  31.     gpio.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
  32.     gpio.GPIO_Mode = GPIO_Mode_AF_PP;
  33.     GPIO_Init(GPIOB, &gpio);
  34.  
  35.     gpio.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 |
  36.                     GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  37.     gpio.GPIO_Mode = GPIO_Mode_Out_PP;
  38.     GPIO_Init(GPIOB, &gpio);
  39.  
  40.     GPIO_StructInit(&gpio);
  41.     gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
  42.     gpio.GPIO_Mode = GPIO_Mode_IPU;
  43.     GPIO_Init(GPIOA, &gpio);
  44. }
  45.  
  46. void nvicConfig(void){
  47.     NVIC_InitTypeDef    nvic;
  48.  
  49.     nvic.NVIC_IRQChannel = TIM4_IRQn;
  50.     nvic.NVIC_IRQChannelPreemptionPriority = 0;
  51.     nvic.NVIC_IRQChannelSubPriority = 0;
  52.     nvic.NVIC_IRQChannelCmd = ENABLE;
  53.     NVIC_Init(&nvic);
  54.  
  55.     nvic.NVIC_IRQChannel = DMA1_Channel7_IRQn;
  56.     nvic.NVIC_IRQChannelPreemptionPriority = 0;
  57.     nvic.NVIC_IRQChannelSubPriority = 1;
  58.     nvic.NVIC_IRQChannelCmd = ENABLE;
  59.     NVIC_Init(&nvic);
  60. }
  61.  
  62. void dmaConfig(void){
  63.     #define TIM4_CCR3_Adr   0x4000083C;
  64.  
  65.     DMA_InitTypeDef     dma;
  66.  
  67.     dma.DMA_PeripheralBaseAddr = (unsigned long int)TIM4_CCR3_Adr;
  68.     dma.DMA_MemoryBaseAddr = (unsigned long int)&wypelnieniePWM;
  69.     dma.DMA_DIR = DMA_DIR_PeripheralDST;
  70.     dma.DMA_BufferSize = 1;
  71.     dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  72.     dma.DMA_MemoryInc = DMA_MemoryInc_Disable;
  73.     dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  74.     dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  75.     dma.DMA_Mode = DMA_Mode_Normal;
  76.     dma.DMA_Priority = DMA_Priority_High;
  77.     dma.DMA_M2M = DMA_M2M_Disable;
  78.     DMA_Init(DMA1_Channel7, &dma);
  79.     DMA_ITConfig(DMA1_Channel7, DMA1_IT_TC7, ENABLE);
  80.     DMA_Cmd(DMA1_Channel7, ENABLE);
  81. }
  82.  
  83. void timerConfig(void){
  84.     TIM_TimeBaseInitTypeDef     TIM_Struct;
  85.     TIM_OCInitTypeDef           TIM_OC_Struct;
  86.  
  87.     TIM_Struct.TIM_Prescaler = 100;
  88.     TIM_Struct.TIM_Period = 99;
  89.     TIM_Struct.TIM_RepetitionCounter = 250;
  90.     TIM_Struct.TIM_ClockDivision = TIM_CKD_DIV1;
  91.     TIM_Struct.TIM_CounterMode = TIM_CounterMode_Up;
  92.     TIM_TimeBaseInit(TIM4, &TIM_Struct);
  93.  
  94.     TIM_OC_Struct.TIM_OCMode = TIM_OCMode_PWM1;
  95.     TIM_OC_Struct.TIM_OutputState = TIM_OutputState_Enable;
  96.     TIM_OC_Struct.TIM_Pulse = 50;
  97.     TIM_OC_Struct.TIM_OCPolarity = TIM_OCPolarity_High;
  98.     TIM_OC3Init(TIM4, &TIM_OC_Struct);
  99.     TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);
  100.  
  101.     TIM_ARRPreloadConfig(TIM4, ENABLE);
  102.     TIM_DMACmd(TIM4, TIM_DMA_Update, ENABLE);
  103.     TIM_Cmd(TIM4, ENABLE);
  104. }
  105.  
  106. void DMA1_Channel7_IRQnHandler(void){
  107.     if(DMA_GetITStatus(DMA1_IT_TC7)!=RESET){
  108.         GPIO_SetBits(GPIOB, GPIO_Pin_15);
  109.  
  110.         DMA_ClearITPendingBit(DMA1_IT_TC7);
  111.     }
  112. }

ODPOWIEDZ