Warning: Illegal string offset 'name' in [path]/includes/functions.php on line 6439
Iesācēja blēņas ar 4x4 plēves klavieri
+
1 2 3

thread: Iesācēja blēņas ar 4x4 plēves klavieri

  1. #1
    Senior Member
    Nov 2009
    Jēkabpils
    2,046

    Post Iesācēja blēņas ar 4x4 plēves klavieri

    Labs vakars.
    Savā vecuma marazmā pievērsos assemblerim. Gribu uztaisīt reālu projektiņu. Protams, var paņemt arduino un viss štokos, bet es negribu (zanudnijs esmu). Vajadzīgi kaut kādi taustiņi, un tad nu sāku ar klavieri. Pilns nets ar copy/paste, bet izglītošanās nolūkos mēģinu "izgudrot divriteni". Uztapa variants ar PCINT pārtraukumu. Rezultātā kods strādā, attiecīgajā reģistrā ierakstās taustiņa numurs (no 1 līdz 16). Bet radās jautājums par parādību - kontaktu drebēšanu. Vai šajā gadījumā tā radīs kaut kādas problēmas? Un vēl esmu strupceļā - PCINT vajadzētu nostrādāt uz līmeņa maiņu. Tas nozīmē, ja es nospiežu taustiņu, šim vajadzētu iziet visas kolonas un notīties no pārtraukuma. Ja taustiņš tiek atlaist, tad pārtraukums notiek, bet kolonas skanētas netiek. Bet es skatos ar osci, ka turot taustiņu nospiestu, klaviere visu laiku tiek skanēta. It kā "kontaktu drebēšana" nevarētu būt vainīga. Jebšu šitas "divritenis"ir galīgi garām?

    :
    ;====================================================================
    ; DEFINITIONS
    ;====================================================================
    .include "C:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\Tools\AVRASM\appnotes\m328Pdef.inc"
    
    .def tmp = r16
    .def tmp1 = r17
    .def tmp2 = r18
    .def tmp3 = r20
    .def btn_num = r19                                                                                                 ;nospiestā taustiņa numurs
    .equ btn_row_0 = PINB0
    .equ btn_row_1 = PINB1
    .equ btn_row_2 = PINB2
    .equ btn_row_3 = PINB3
    .equ btn_col_0 = PORTB4
    .equ btn_col_1 = PORTB5
    .equ btn_col_2 = PORTB6
    .equ btn_col_3 = PORTB7
    .equ row_count = 4 
    
    ;====================================================================
    ; RESET and INTERRUPT VECTORS
    ;====================================================================
    
          ; Reset Vector
          rjmp  Start
    .org 0x0006
          rjmp btn_push                                ;PCINT0 pārtraukuma vektors
    
    ;====================================================================
    ; CODE SEGMENT
    ;====================================================================
    
    Start:
          ldi tmp3, row_count                                                                         ;klavieres rindu skaits, šoreiz 4
          ldi tmp, (1<<PIND0)|(1<<PIND1)|(1<<PIND2)|(1<<PIND3)|(1<<PIND4)        
          out DDRD, tmp                                                                                ;PORTD0...4 pataisam par izejām LEDiem (kontrolei)
          ldi tmp, (1<<btn_col_0)|(1<<btn_col_1)|(1<<btn_col_2)|(1<<btn_col_3)
          out DDRB, tmp                                                                                ;PORTB4...7 pataisam par izejām - klavieres kolonas
          ;clr tmp
          ;out PORTB, tmp
          ldi tmp, (1<<btn_row_0)|(1<<btn_row_1)|(1<<btn_row_2)|(1<<btn_row_3)
          out PORTB, tmp                                                                              ;uzliekam pull-up klavieres rindām
          ldi tmp, (1<<PCIE0)
          sts PCICR, tmp                                                                               ;atļaujam PCIE0 pārtraukumu
          ldi tmp, (1<<PCINT0)|(1<<PCINT1)|(1<<PCINT2)|(1<<PCINT3)
          sts PCMSK0, tmp                                                                            ;pārtraukums strādās uz izmaiņām PCINT0...3
          sei                                                                                               ;atļaujam pārtraukumus
          
    Loop:
          rjmp  Loop
    
    btn_push:
    ;      clr btn_num
          in tmp2, PinB              ;ielasam reģistrā klavieres rindas                            
          ori tmp2, 0xf0             ;uzliekam masku - apskatam tikai PB0...3 bitus
          cpi tmp2, 0xff             ;ja visi "1", tad poga ir palaista vaļā, un
          breq no_btn               ;lecam uz pārtraukuma beigām
          clr btn_num               ;ja ir kāda "0", tad iztīram taustiņa numura reģistru
          clr tmp2                    
          ser tmp1                   ;saliekam reģistrā, kuru izmantojam kolonu skanēšanai vieniniekus
    next_col:                        ;meklējam, kurā kolonā nospiestais taustiņš
          sec                          ;C karogā ierakstam "1"
          tst btn_num              ;ja taustiņa numurs ir nulle,
          brne not_first_col       ;tad pārlecam
          clc                           ;ja nē, tad C karogā ierakstam "0"
    not_first_col:          
          ror tmp1                   ;šiftojam kolonu skanēšanas reģistru
          out PORTB, tmp1        ;rakstam iekš PORTB izejām
          add btn_num, tmp3     ;pieskaitam taustiņa numuram 4
          in tmp2, PinB              ;nolasam klavieres rindas 
          ori tmp2, 0xf0             ;uzliekam masku
          cpi tmp2, 0xff             ;salīdzinam ar 255
          breq next_col             ;ja visi "1", tad lecam atpakaļ pārbaudīt nākamo kolonu
          sub btn_num, tmp3     ;atskaitam no taustiņa numura 4
    next_row:                       ;meklējam, kurā rindā nospiestais taustiņš
          inc btn_num              ;pieskaitam taustiņa numuram "1"
          lsr tmp2                    ;šiftojam 
          brcs next_row           ;ja C karogā nav "0", tad lecam atpakaļ
    no_btn:
          ldi tmp1, 0x0f    
          out PORTB, tmp1       ;nometam visas kolonas uz "0"
          out PORTD, btn_num  ;iededzam nospiestā taustiņa numuram atbilstošos LEDus
          reti
    ;====================================================================

  2. #2
    Senior Member
    Jun 2006
    Cēsu novads
    986

    Labvakar!
    Beidzot kāds pievērsies assemblerim! Citādi, galīgi nav ar ko apspriest AVR programmēšanu šajā valodā. Jāatzīstas pašreiz īsti nav laika iedziļināties kodā, jo jāsteidz cits darbs, bet uzreiz varu teikt ka ar kontaktu drebēšanu visticamāk vajadzēs cīnīties. Neesmu tieši ar plēves klavierēm ņēmies, bet visādām podziņām un slēdžīšiem kontaktu drebēšana ir aktuāla. Jāsaka gan, ka viss, kas notiek ar klaviatūru ir tik lēns process, ka tam pārtraukumus neizmantoju, parasti šādas lēnās lietas apskatu reizes 40 sekundē un, ja kaut kas izmainās, piefiksēju jauno vērtību un uzmetu skaitītāju. Ja skaitītājs noskaita līdz nullei un jaunā vērtība joprojām ir aktuāla, tad pieņemu, ka taustiņš tiešām ir izmainījis savu stāvokli. Par pārtraukuma atkārtošanos šajā gadījumā, man uzkrita, ka pārtraukuma laikā kaut kas tiek rakstīts reģistrā PORTB, tas ir turpat, kur PINB izmaiņas izsauc pārtraukumu. Vai tas nevarētu izsaukt atkārtotu pārtraukumu? Bet atkārtošos - neesmu iedziļinājies kodā, vienkārši tas iekrita acīs. Otra lieta, kam šajā gadījumā nav nozīmes, bet ja galvenā programmas cilpa ir garāka un sarežģītāka, kas noteikti jāņem vērā - sākot apstrādāt pārtraukumu jāsaglabā statusa reģistrs SREG un izejot no pārtraukuma jāatliek atpakaļ.

  3. #3
    Senior Member
    Nov 2009
    Jēkabpils
    2,046

    Patiesībā, mana pēdējā tikšanās ar kaut ko līdzīgu bija ... ui cik sen. Automātiskais numura noteicējs, jeb AONs, kā šo sauca. Mikrokontroliera lomu gan spēlēja Z80. Tur klaviatūras "apprasīšana" notikās izmantojot vienīgo ārējo pārtraukumu kaut kādas ... nezin cik (netceros vairs) reizes sekundē. Vienkārši ieraudzīju piemēru ar šo PCINT un rakstīju (mācīšanās nolūkos) pa savam.
    Jā, kad biju uzrakstījis postu, jau iedomājos par šo variantu, ka iekš pārtraukuma kaut kas notiek ar to portu, tad tas varētu būt iemesls. Tikai, vai tad ieejot pārtraukumā, pārtraukumi neaizliedzas? Jāmācā matčasķ
    Taisnība, par to statusa reģistru zinības apguvu, vienkārši šeit neierakstīju tās rindiņas.
    p.s. bet assemblers ir foršs

  4. #4
    Senior Member
    Jun 2006
    Cēsu novads
    986

    Ieejot pārtraukumā pārtraukumi aizliedzas, bet ar RETI atkal atļaujas. Ieejot pārtraukumā, tev nometas tie karogi kas izsauc pārtraukumu, bet ja tu pārtraukumā kaut ko sadari, kas izsauc jaunu pārtraukumu, tad tiklīdz pārtraukumi tiek atļauti, tā pārtraukums notiek. Lai tā nenotiktu, tad tad pārtraukumā pēc darbībām ar PORTB drošības labad būtu jānomet tas pārtraukuma karogs ierakstot tur vieninieku, kā teikts šeit:
    • Bit 1 – PCIF1: Pin Change Interrupt Flag 1
    When a logic change on any PCINT[14:8] pin triggers an interrupt request, PCIF1 becomes set (one). If the I-bit
    in SREG and the PCIE1 bit in PCICR are set (one), the MCU will jump to the corresponding Interrupt Vector.
    The flag is cleared when the interrupt routine is executed. Alternatively, the flag can be cleared by writing a
    logical one to it.

  5. #5
    Senior Member
    Jun 2006
    Cēsu novads
    986

    Atvainojos, es par PCIF1, bet vajadzēja par PCIF0, bet būtība jau tā pati.

  6. #6
    Senior Member
    Nov 2009
    Jēkabpils
    2,046

    Vo, paldies. Nepadomāju, ka tas pārtraukums paliek atmiņā. Mēģināšu. Droši vien jau, ka šis klavieres apprasīšanas veids paliks tikai mācīšanās nolūkos, bet jātiek galā.

  7. #7
    Senior Member
    Mar 2007
    1,597

    Atbalstu ideju ka klavieres skaneeshanu nevajag taisiit ar paartraukumiem (to vienmeer maz un svariigaakaam lietaam vajadziigi).
    Labaak pievienot citam cikliskam procesam - piemeeram dinamiskaas indikaacijas regjeneraacijai (arii porti tad mazaak vajadziigi jo ar tiem pashiem klavieres matricu var adreseet).

  8. #8
    Senior Member
    Mar 2007
    1,597

    Jāsaka gan, ka viss, kas notiek ar klaviatūru ir tik lēns process, ka tam pārtraukumus neizmantoju, parasti šādas lēnās lietas apskatu reizes 40 sekundē un, ja kaut kas izmainās, piefiksēju jauno vērtību un uzmetu skaitītāju. Ja skaitītājs noskaita līdz nullei un jaunā vērtība joprojām ir aktuāla, tad pieņemu, ka taustiņš tiešām ir izmainījis savu stāvokli
    Mans "viena pirksta" klavieres algoritms taads:
    Pogai ir viens stabils staavoklis - atlaista.
    Ja konstateeta nospieshana tad uzsaakam taimautu kura laikaa atlaishana tiek ignoreeta bet nospiests staavoklis taimauta laika skaitiishanu uzsaak no jauna.
    Parasti taada pieeja tiek kritizeeta sakot ka impulsveidiigs trauceejums var tikt uztverts kaa pogas nospieshana.
    Man domaat tomeer trauceejumus sheemtehniski jaanoveersh un programmistam tikai ar kontaktu drebeli jaaciinaas.

  9. #9
    Senior Member
    Nov 2009
    Jēkabpils
    2,046

    Oi, atmiņa pievīla. Toč, manam vienīgajam kontaktam ar assembleri AONam klaviatūras apprasīšana notika kopā ar dinamisko indikāciju. Pārtraukums uz klavieri bija ZX Spectrum (ja kāds vēl tādu atceras).
    Nu jā, bet kas to nospiešanu konstatē? Vai iekš galvenā programmas cikla katrā caurgājienā vienmēr tiek pārbaudīts visu pogu stāvoklis? Un nospiešanas gadījumā apakšprogramma? Un vai tad gadījumā, ja nepieciešami kādi svarīgi aprēķini, nu nezinu, tipa enkodera apkalpošana un pozīcijas aprēķināšana, vai tāda pogu apprasīšana nav jāaizliedz?

  10. #10
    Senior Member
    Jun 2006
    Cēsu novads
    986

    Katrā galvenās programmas cikla caurgājienā to galīgi nav nepieciešamas darīt. Es to daru šādi. Uzstādu kādu no taimeru pārtraukumiem ar tādu periodu, ka tas realizēsies 40 reizes sekundē. Pašā taimera pārtraukumā neko īpašu nedaru, tikai uzmetu pazīmi, ka tāds pārtraukums bijis. Galvenajā programmas ciklā, pamanot šo pazīmi, eju izpildīt apakšprogrammu, kurā apkopotas visas tās lietas, kas jādara 40 reizes sekundē. Pabeidzot šo apakšprogrammu nometu arī taimera uzmesto pazīmi. Un līdz nākošajam taimera pārtraukumam, kas šo pazīmi atkal uzmetīs, galvenais cikls griežas pa mazo apli. Pārtraukumos bez īpašas vajadzības vispār cenšos neko lieku nedarīt, jo pārtraukuma laikā citi pārtraukumi tiek aizliegti un atmelis būtībā ir kurls un akls un var nogulēt kaut ko svarīgu. Var jau arī pārtraukuma laikā piespiedu kārtā atļaut pārtraukumus, bet ar to ir jābūt ļoti uzmanīgam, var iebraukt dziļās auzās. ir gadījies.

+