Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
ATmega168 7-Segmentni Display
Drustvo, predlazem vam da Source Code prebacide na GIT i tamo da lepo operisete sa programom i izmenama.
Ovo sa RAR arhivama je malo neprakticno, ne moze uopste tema da se prati.

Otvorite GIT nalog, moze da se prikljucite u grupu foruma ili kako god vam odgovara:
https://github.com/yu3ma/

Ako niste koristili GIT do sad a pisete bilo kakav programerski code, pod obavezno da proucite i pocnete da koristite.
Postoji 10-ak operacija koje se vrte nad fajlovima i verzijama i to je prakticno sve sto treba da se oko toga poznaje, sve ostalo je isto kao i do sad sto ste pisali samo od sad vas source stoji u specialnoj bazi koja cuva potpun integritet svih fajlova i delova programa koji su ukljuceni u kontrolu revizije. Birajte javni nalog ili privatni ili lokalni GIT server ...
Reply
Prvo uradiš lsr višeg bajta pa onda ror nižeg bajta. Dakle, ako je podatak predstavljen kao r22:R21 imaš sledeće.

lsr r22
ror r21

Time si rezultat podelio sa 2. Još jednom isto to i tvoj konačni rezultat biće smešten u paru r22:r21.
Pomeranje za jedno mesto u desno binarnog podatka predstavlja deljenje sa 2.
Pomeranje za jedno mesto u levo binarnog podatka predstavlja množenje sa 2.
Reply
Pokusao sam sa ovim...vidim da ASM ima iste direktive kao i C:
Sa MAX6675<<5 shiftujem 5 mjesta u lijevo...

Read_Temp_MSB:
      in R21, SPSR ; Read Data
      sbrs R21, SPIF        ; Wait Unti Read Data
      rjmp Read_Temp_MSB
      ldi R21, SPDR
      out HIGH(MAX6675<<5/4), R21 ; Read Msb From MAX6675
      out SPDR, R20 ; Send Dummy Byte

Sa MAX6675>>3 shiftujem desno 3 mjesta...
Read_Temp_LSB:

      in R21, SPSR ; Read Data
      sbrs R21, SPIF ; Wait Unti Read Data
      rjmp Read_Temp_LSB
      ldi R21, SPDR
      out Low(MAX6675>>3/4), R21 ; Read Lsb From MAX6675


A /4 dijelim reziltat sa 4 (posto se mora pomnoziti sa 0,25C rezolucije maxa da bi se dobila temperatura....a ja to radim 1/0,25 = 4 posto ASM nema jednostavnu ALU za rad sa floating point).

Pokrenem ja simulaciju i na brojkama samo 208 mislim da nisam dobro ocitao vrijednost MAX6675 u Loop glavnome programu gdje on uzima MAX6675 i onda extracta prvi drugi i treci digit...jednostavno ne uzima vrijednost MAX6675 sa FLASH-a...tu je sada rar sa kodom...

Dakle sa ovim kodom ocekujem da se na displayu ispise 143 do 149 posto je temperatura postavljena na 146 a MAX ima -/+3C pogresku...

Evo i slike sheme iz simulatora da mozda nisam sto krivo spojio..pa da se i to vidi...





.rar   Projects.rar (Size: 1,67 KB / Downloads: 2)
SAMO-BANOVAN OD 01.11.2024
Reply
Nije dobro ovo prethodno. Probaj kako sam ti napisao u prethodnoj poruci. Dva puta odradiš pomeranje u desno i podelio si sa 4. Sve gotovo za čas posla.
Reply
Read_Temp_MSB:
      in R22, SPSR ; Read Data
      sbrs R22, SPIF        ; Wait Unti Read Data
      rjmp Read_Temp_MSB
      ldi R22, SPDR
      out SPDR, R20 ; Send Dummy Byte

Read_Temp_LSB:
      in R21, SPSR ; Read Data

      sbrs R21, SPIF ; Wait Unti Read Data
      rjmp Read_Temp_LSB
      ldi R21, SPDR

Sada ti je rezultat u paru R22:R21

Odradiš:

    lsr R22
    ror R21
    lsr R22
    ror R21

I konačan rezultat konverzije ti je R22:R21. Posle toga sa njim radiš šta hoćeš.
Reply
Napravio sam ovako ali compiler se i dalje buni:

lsr R22 ; Shift Left 2times
ror R21
lsr R22
ror R21

out HIGH(MAX6675/4), R22 ; Read Msb From MAX6675
out Low(MAX6675/4), R21 ; Read Lsb From MAX6675

To je dodano poslije ldi R21, SPDR iz tvoga koda...dakle postavljam high i low byte podijelim sa 4..i compiler javlja gresku:

error: Operand 1 out of range: 0x40

Ta greska se odnosi na ovaj LOW(MAX6675/4), R21

Ako sam dobro shvatio imam 16-bitni byte sa SPI koji sam procitao sa MAX6675, i shiftranjem dva puta 2x2byte shifrtujem desno sto ce biti da 16-4=12byteova dobivam tocno koliko je velicina temperature u registru MAX6675...(s time da 0 1 2 su ID maxa i opetn ili close thermocuple)
SAMO-BANOVAN OD 01.11.2024
Reply
Ne ide tu OUT već STS. Pogledaj razliku između ove dve komande

Dakle:

STS HIGH(MAX6675), R22
STS LOW(MAX6675), R21
Reply
Sta ti znaci ovo:
LOW(MAX6675/4)???
Goran ti je lepo pokazao kako se deli pomocu siftovanja. Ne razumem sta je ovo sto si napisao.
Reply
STS je Store To SRAM, dakle pospremi vrijednost R22 i R21 registra u MAX6675 lokaciju SRAM-a...a OUT je pospremi vrijednost registra u drugi registar ili port, timer etc...da ja nisam zapisao u SRAM zato nije htjelo da radi...

ovo mi je sada jasno..byte shifting...i upis vrijednosti u SRAM preko STS naredbe..ali ostaje mi enigma zasto nece da u loop petlji nakon sto se sa naredbe:

rcall readThermoCouple vrati u Loop treba da je memorijski pointer na MAX6675 popunjen sa prethodnom vrijednoscu HIGH i LOW (STS) a ja dobivam sa:

lds R16, HIGH(MAX6675%1000/100) ; Read Digit1 Index
lds R17, Low(MAX6675%1000/100)

sve osmice na displayu....prije sam imao ldi ali posto sada citam sa memorijske lokacije moram da koristim lds naredbu ili ti Load Direct From SRAM....ali samo 888 mi je na 7 segmentnom displayu...evo najbolje kod...koji sam prepravio kako si mi gore napisao:

Jooj jesam baksuz...da gorankg je lijepo objasnio shiftovanje a ja i dalje djelio sa /4 eh to sam sada izbacio ali jos mi gore ostaje spomenuti problem... 888 na displayu...sad dali krivo citam sa SRAM-a pointer na kojem se cuva vrijednost ili sam negdje drugdje zabrljao..posto sada ima postavljene sve vrijednosti...evo najbolje kod pa ako moze jos malo smjernice kako mora da se odradi tj gdje sa pogrijesio...


.rar   Projects.rar (Size: 1,73 KB / Downloads: 2)
SAMO-BANOVAN OD 01.11.2024
Reply
Rezultat ovoga:

MAX6675%1000/100

je promenljiva dužine jedan bajt tako da

HIGH(MAX6675%1000/100)
LOW(MAX6675%1000/100)
ne znači ništa.


Treba da ti indeks za Digit1 bude:

lds        R16, (MAX6675%1000/100)

I tako za sve ostale cifre.
Reply
Postavio tako i dobivam 088..na displayu..
SAMO-BANOVAN OD 01.11.2024
Reply
Probaj ovako za jednu cifru:

    ; Convert Thermocouple Temperature
    ldi        ZH, HIGH(digit)                ; Load Start Z-Address Of Digit Array (Flash)
    ldi        ZL, Low(digit)
    
    lds        R17, (MAX6675%1000/100)
    add       ZL, R17 
    brcc    no_carry
    inc      ZH
no_carry:
    lpm       R23, Z                        ; Read Digit1 From Flash
Reply
Probao za jednu cifru i za sve tri...za ostale dvije sam stavio no_carry2 i no_carry3 ali sada su samo 0 0 0 na displayu....trebalo bi ovo nekako u simulatoru da se upise preko SPI vrijednost nekva temperature i da se ide linija po liniju...gledam bas sada kako to izvesti i onda da se prate registri i sto se dogadja u SRAMu i registrima...
SAMO-BANOVAN OD 01.11.2024
Reply
OK mali napredak...shifting mora da bude tocno ovako:

         lsr R22           ; Shift Right 8bytes(4times x 2byte)

         ror R21
         lsr R22
         ror R21
         lsr R22
         ror R21
         lsr R22

Isao sam rucno pratiti vrijednosti u simulatoru i od 16 bitnog ulaza: 1D80 dobivam na izlazu nakon shiftovana 1B0 sto odgovara brojki 432decimalno...01 se upisuje u R22 tj HIGH a B0 u R21 LOW...i to u space registre R0 i R1 pomocu naredbe sts:

sts HIGH(MAX6675), R22        ; Read Msb From MAX6675
sts Low(MAX6675), R21          ; Read Lsb From MAX6675

U simulatoru vidim da mi space registri imaju vrijednost:

R0  => B0
R1  => 01

Sto je tocna vrijednost, sada problem je kod mene u ovoj naredbi lds koja ne cita sa tih space registra i vraca uvijek 00 i zato su mi na displayu 88 tj cudni brojevi:

lds R16, (MAX6675/4%1000/100)            ; Read Digit1 Index

Dakle lds se NEMOZE korisiti za citanje iz space registara od R0...R15 nego treba na drugaciji nacin...i to sad trazim jos ako ko zna moze da napise...tu je bila druga greska..nakon toga mislim da ce da radi program kako treba..dakle kako procitati vrijednost is R0 i R1 da mogu onda lijepo napraviti matematiku i onda prikazati na displayu...probao sam i ls i ldi ali to je za direkt registre a ja vrijednost imam u space registrima...probao sam i direktan upis u SRAM ali onda nemogu da radim matematiku...tako da ovaj lds treba drguacije napisati da procita vrijednost..jer ovom naredbom R16 bi trebao da ima vrijednost B0 a ja imam vrijednost 00.

Ovako sam isao shifting pjeske da sam nasao koji kod treba da ide i sto treba da se dobije:

SAMO-BANOVAN OD 01.11.2024
Reply
Evo, bio sam malo aktivan, pa sam usao malo u ASM za AVR. Ronovar, AVR asembler nije bas jednostavan i intuitivan. Arhitektura procesora je napravljena da sve mora da ide preko R0-R31 registara. Cak i kada definises neku svoju promenljivu, njoj pristupas indirektno pomozu X, Y ili Z registara.
Ovo sto si napisao:

lds R16, (MAX6675/4%1000/100)

ne moze da se izvrsi. To bi znacilo da si u jednoj instrukciji izvrsio nekoliko deljenja, a to nije moguce. ASM je direktno povezan sa MCU-om, tj. svaka instrukcija odgovara CPU operaciji.
Ti citas AD preko SPI i zelis da ga prikazes na displeju. Tebi treba konverzija iz HEX ili binarnogu BCD. Za ovo je potrebno napisati program.
Druga bitna stvar je mnozenje rezultata sa 0,25. To ti takodje nije tako jednostavno. Bolje je da prvo uradis prikaz rezultata AD konverzije. Takodje, nemoj uopste da se zezas sa AD konverzijom, vec definisi promenljivu i u nju upisi neku vrednost koju zelis da prikazes.
U prilogu ti je program za ovo.


Attached Files
.asm   main.asm (Size: 1,66 KB / Downloads: 9)
Reply
Posto sam uvidio da ALU matematicke operacije su dosta zahtjevne za raditi u ASM skinuo sam ImageCraft ICCAVR C Compiler za AVR.

U prilogu postavljam c source code koji radi preko timer1 CTC interrupta pa ako moze da se provjeri jeli sve ok sto se tice programa i pisanja programa u c-u.

Kompilirao dobio 152byta zauzeca FLASH-a (asm je to odradio sa 72byta  ali je kompleksniji)...flashao ATmega328p i LED dioda blinka u intervalu 1secunde...za sada mi se C cini puuunoo jednostavniji od ASM pa i ima dosta primjera a i lagan mi se cini na prvu...

Evo koda pa ako nema greske onda da po protokolu napisem program koji ce da broji od 000 - 999 na 7 segmentnom displayu...pa onda dalje...


.rar   SolderStation.rar (Size: 814 bytes / Downloads: 2)
SAMO-BANOVAN OD 01.11.2024
Reply
Prijatelju,

gorankg i ja ti uporno pricamo da koristis Atmel Studio, a ti uporno ides na neke druge kompajlere. Zapamti sledece: Firma koja se nekada zvala ATMEL, danas su kupljeni od strane MICROCHIP-a je napravila AVR mikrokontrolere. Ista ta kompanija je za svoje klijente napravila i Atmel Studio za programiranje. Uopste mi nije jasno zasto onda programirati okruzenju koje je razvila neka deseta kompanija!!!

Vec sam ti pisao:
Za PIC MCU programiranje - MPLAB
Za AVR MCU programiranje - Atmel Studio
Za STM32 programiranje - Atollic True Studio
Za MSP MCU programiranje - IAR
...
...
Reply
Izvinjavam se....za atmel studio nisam ni gledao dali ima podrsku za C/C++ i kad ono ima.

Evo radit cu u Atmel Studio i C project..u prilogu kod za CTC Timer1 Interruptom pa ako moze da se pogleda dali tako treba da se radi u C-u.

Kompilirao, Flashao i LED blinka Smile


.rar   Solder_Station.rar (Size: 875 bytes / Downloads: 3)
SAMO-BANOVAN OD 01.11.2024
Reply
PHP Code:
/*
 * SolderStation.c
 *
 * Created: 15.4.2018. 9:27:37
 * Author : Robert
 */ 

#include <avr/io.h>
#include <avr/interrupt.h>

/* Initialize Timer1 */
void timer1_init(void){
    
/* Prescaler = 1024, CTC Mode */
    
TCCR1B |= (1<<WGM12)|(1<<CS12)|(1<<CS10);
    
/* Initialize Counter */
    
TCNT1 0;
    
/* Initialize Compare Value 1sec */
    
OCR1A 18000;
    
/* Enable Compare Interrupt */
    
TIMSK1 |= (1<<OCIE1A);
    
/* Enable Global Interrupts */
    
sei();
}

/* LED Blink */
ISR (TIMER1_COMPA_vect){
    
/* Toggle LED */
    
PORTD ^= (1<<1);
}

int main(void)
{
    
/* LED On PORTD.1 */
    
DDRD |= (1<<1);
    
/* Initialize Timer1 */
    
timer1_init();
 
   /* Replace With Your Application Code */
 
   while (1
 
   {
 
   }


Ja ne mogu da pratim code drugacije ... : )
Reply
Ronovar,

program ti ocigledno radi. Pogledaj program ispod i uporedi sa tvojim programom, cisto da vidis kako malo lepse da organizujes program.

PHP Code:
#include <avr/io.h>
#include <avr/interrupt.h>


#define LED_ON()        PORTD |= 0b00000010
#define LED_OFF()        PORTD &= 0b11111101
#define LED_TOGGLE()    PORTD ^= 0b00000010

/* Initialize Timer1 */
void timer1_init(void){
    
/* Prescaler = 1024, CTC Mode */
    
TCCR1B |= (1<<WGM12)|(1<<CS12)|(1<<CS10);
    
/* Initialize Counter */
    
TCNT1 0;
    
/* Initialize Compare Value 1sec */
    
OCR1A 18000;
    
/* Enable Compare Interrupt */
    
TIMSK1 |= (1<<OCIE1A);
}

/* LED Blink */
ISR (TIMER1_COMPA_vect){
    
/* Toggle LED */
    
LED_TOGGLE();
}

void Init_MCU(void)
{    
    
DDRD |= (1<<1);                            // PORTD.1 is output
    
    
timer1_init();                            // Initialization of the TMR1
    
    
sei();                                    // Enable Global Interrupts

}
int main(void)
{
    
    
Init_MCU();                                        // Initiazalition of the MCU
    
    /* Replace With Your Application Code */
    
while (1)
    {
    }

Reply


Forum Jump:


Users browsing this thread: 4 Guest(s)