PIC 16F887 en MikroBasic

Bavelt

Golden Member

Ik twijfel er overigens zelf aan of ik de pinnen wel goed heb.

Volgens de Datasheet is ICSPDAT Poort B.7 (pin 40 van de 887) de ICSPCLK Poort B.6 (Pin 39).

Voor de latch heb ik B.2 genomen.

Maar ik zie dat Poort C4 'SDA' heeft staan en C.3 'SCL'. Of is dat weer voor de i2c?
Ik weet niet helemaal goed meer wat wat nu is en hoe ik het moet lezen.

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Er valt niks te kiezen (dat kan alleen met nieuwere chips met een PPS); de 887 heeft maar één vaste SPI:
Pin C3 = SCLK
Pin C4 = MISO <- in
Pin C5 = MOSI -> uit

SDA/SCL is altijd i2c

[Bericht gewijzigd door Arco op zaterdag 2 november 2019 15:38:50 (15%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Ik heb het veranderd:
De klok op C.3, De Data op C.4 en de 'latch' op C.5

Als de 887 één vaste SPI heeft, dan zou je dus in principe de poorten niet hoeven te definiëren.
Toch?

pic basic code:

 Program Matrix

Dim ClockPin as sbit at PORTC.3
DIM Latch as sbit at PORTC.5
DIM Datapin as sbit at PORTC.4

Dim Kolom as Byte
Dim Inhoud as Byte

Sub Procedure Max_Write()
latch = 0
SPI1_Write(Kolom)
SPI1_Write(Inhoud)
latch = 1
end sub

Sub Procedure Max7219_Init()
Spi1_Init()
                                    'Hier worden de registers geïnitialiseerd
Kolom = $09                         'Decode Mode Register:
Inhoud = $00                        'Code B for digits
Max_Write ()

Kolom = $0B                         'Scan-Limit Register:
Inhoud = $07                        'Digit 0,1,2,3,4,5,6,7 ($00-$07)
Max_Write()

Kolom = $0C                         'Shutdown Register:
Inhoud = $01                        'Normal Operation
Max_Write()

Kolom = $0A                         'Intensity Register
Inhoud = $00
Max_Write()
delay_ms(500)
end sub

Sub Procedure Display_Testen()      'Testen van het display; alle LEDS aan
Kolom = $0F
Inhoud = $01
Max_Write()
DELAY_MS(1000)

Kolom = $0F                         'Weer terugzetten naar normal operation
Inhoud = $00
Max_Write()
DELAY_MS(1000)

end sub

Sub Procedure Uitzetten_Leds()
'leds uitzetten
DIM i1 AS BYTE
FOR i1 = 1 TO 8
  Kolom = i1
  Inhoud = %00000000
  Max_Write()
  Delay_Ms(500)
NEXT i1
end sub
 
 Sub Procedure Aanzetten_Leds()
'leds aanzetten
Dim i1 as Byte
FOR i1 = 1 TO 8
  Kolom = i1
  Inhoud = %11111111
  Max_Write()
  delay_ms(500)
NEXT i1
End sub

main:

'        76543210
TRISB = %11111111
TRISC = %11111111

 Display_Testen()
 Uitzetten_Leds()
 Aanzetten_Leds()

'Klaar
while true wend

END.  

Maar het display doet nu helemaal niks meer.

Fouten zijn het bewijs dat je het probeert..
Bavelt

Golden Member

SDA/SCL is altijd i2c

In de datasheet zie ik SCL = C.3 en SDA = C.4.

Maar dan heb ik dus de SPI op de I2C poorten zitten?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

C4 is de ingang, C5 de uitgang (zo gaat 't dus niet werken...
Ik denk ook niet dat de C3/4/5 als chipselect kunt gebruiken als de SPI actief is, daar moet je een andere pin voor nemen.

De SPI en I2C zitten op dezelfde pinnen, ligt eraan welke je aan zet...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Ik begin er nu steeds minder van te begrijpen vrees ik.
In het PICbasic programma leek het simpel en het werkte ook nog.

Nu even terug naar af: Ik heb een Module met een MAX7219 en een LED matrix van 8*8.
Daar zitten 5 pennen op:
VCC en GND. Dat is makkelijk.

Dan is er een DIN (data), een CLK (klok) en een CS (Chip select).

Wie sluit ik nu waar op aan om het werkend te krijgen op de 887?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Aan de SPI bus. SCK/C3 is de clock, SDO/C5 (MOSI vind ik zelf duidelijker) is de data output, en de chip select mag je zelf kiezen... ;)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Er gaat misschien toch een lampje bij me branden.

Ik was gefixeerd op SDA. En gebruikte die voor de SPI-Data.

Maar ik begrijp nu dat de benaming SDA slaat op de data van de I2C.

Terwijl SDO datapen van de SPI is.

Heb ik het goed?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Ja,

SDO is Slave Data Out (of soms ook uitgelegd als Serial Data Out)
SDA/SCL is i2c, heeft niets met SPI te maken...

Oorspronkelijk heette die pen bij Motorola MOSI (Master Out Slave In, een stuk duidelijker...

[Bericht gewijzigd door Arco op zaterdag 2 november 2019 16:38:55 (31%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

De Klok op C3, De data op C5 en de Latch op C7.

Maar het display reageert niet (springt na verloop van tijd wel spontaan aan d.w.z alle led's aan. )

pic basic code:

Program Matrix

Dim ClockPin as sbit at PORTC.3
DIM Latch as sbit at PORTC.7
DIM Datapin as sbit at PORTC.5

Dim Kolom as Byte
Dim Inhoud as Byte

Sub Procedure Max_Write()
latch = 0
SPI1_Write(Kolom)
SPI1_Write(Inhoud)
latch = 1
end sub

Sub Procedure Max7219_Init()
Spi1_Init()
                                    'Hier worden de registers geïnitialiseerd
Kolom = $09                         'Decode Mode Register:
Inhoud = $00                        'Code B for digits
Max_Write ()

Kolom = $0B                         'Scan-Limit Register:
Inhoud = $07                        'Digit 0,1,2,3,4,5,6,7 ($00-$07)
Max_Write()

Kolom = $0C                         'Shutdown Register:
Inhoud = $01                        'Normal Operation
Max_Write()

Kolom = $0A                         'Intensity Register
Inhoud = $00
Max_Write()
delay_ms(500)
end sub

Sub Procedure Display_Testen()      'Testen van het display; alle LEDS aan
Kolom = $0F
Inhoud = $01
Max_Write()
DELAY_MS(1000)

Kolom = $0F                         'Weer terugzetten naar normal operation
Inhoud = $00
Max_Write()
DELAY_MS(1000)

end sub

Sub Procedure Uitzetten_Leds()
'leds uitzetten per kolom
DIM i1 AS BYTE
FOR i1 = 1 TO 8
  Kolom = i1
  Inhoud = %00000000
  Max_Write()
  Delay_Ms(500)
NEXT i1
end sub
 
 Sub Procedure Aanzetten_Leds()
'leds aanzetten per kolom
Dim i1 as Byte
FOR i1 = 1 TO 8
  Kolom = i1
  Inhoud = %11111111
  Max_Write()
  delay_ms(500)
NEXT i1
End sub

main:

'        76543210
TRISC = %11011111

 Display_Testen()
 Uitzetten_Leds()
 Aanzetten_Leds()

'Klaar
while true wend

END.  
Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

pic basic code:

 TRISC = %01011111

Geeft geen ander resultaat.

Extra opmerkelijk: als alle led's branden, dan resetten ze niet meer na opnieuw starten van programma. Je moet de voeding er af halen en weer aanzetten om ze uit te krijgen.

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Spi1_init() wordt nooit uitgevoerd... (dan gebeurt er ook niks)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Was inderdaad zo en had ik over het hoofd gezien.
Maar dat bracht niet de enige oplossing.

Wat wel de oplossing bracht was

pic basic code:

ANSEL.C = 0 

Op zich merkwaardig (voor mij althans); uit de datasheet haalde ik niet dat Poort C ook analoog kon zijn.

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Wat wel de oplossing bracht was ANSEL.C = 0

???
'C' is de carryflag, die heeft hier totaal niks te zoeken...
Toevallig is die '0', dus met ANSEL.C reset je bit 0 (RA0 is dan digitaal)
Heeft niks met portC of SPI te doen. Je zal wel wat anders hebben gedaan, dit kan 't niet zijn.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Je hebt wederom gelijk.. :D

Omdat het gisteren niet werkte heb ik getest of de C-poort wel iets deed. Door een Ledje aan een van de C-Poorten te hangen en te laten knipperen.
Lukte niet.
Toen dacht ik: misschien staat hij niet als digital output?
En zag ik dat hij ansel.c = 0 accepteerde en het ding deed het ook ineens.

Vanochtend de Ansel weggehaald en hij doet het nog steeds...

Beetje onverklaarbaar, maar het werkt en ik kan in ieder geval verder. ;)

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

ANSEL.C mag NOOIT.
Zoals gezegd is dat de bit constante voor het Carrybit. ANSELC.x kan wel. (maar niet bij de 887... ;) )

[Bericht gewijzigd door Arco op zondag 3 november 2019 11:35:49 (14%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Ik ben nu aan het puzzelen hoe ik een tweede MatixLed met de MAX7219 aan boord kan koppelen aan de PIC, waarbij de ene matrix iets anders vertoont dan de andere.

Bijvoorbeeld: ik tel tot 100. De rechter MatrixLED geeft de aantallen aan, de linker de tientallen.

Ik heb de CLK en SDO aan elkaar geknoopt.
Het enige dat overblijft om te schakelen van de ene naar de anders is dan de CS.

Maar hoe doe je het dan met de data?
Bijvoorbeeld hoe geeft je het getal 21 aan?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

De SCLK moet van beide aan elkaar, de /CS(LOAD) van beide moet aan elkaar.
De SDO komt aan DIN van de eerste chip. DOUT van de eerste chip gaat naar DIN van de tweede chip.
Ik heb ze nooit gebruikt, maar ik neem aan dat je gewoon 16 datawords toe moet schrijven. (de eerste 8 gaan dan naar display 2)
(met in ditgeval het bitpatroon '21')

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

De eerste display schuift via DOUT alles door (na 16,5 clockpulsen las ik in de DS van de MAX7219).

Maar dan toont Display2 dezelfde inhoud als Display1.

Maar wat je wilt is dat bv na de het cijfer 9 van display 1,
display2 eentje hoger toont.

(Dus tot 100 tellen)

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Wat ik begrijp is dat je ?CS laag maakt, twee datawords verstuurt, en dan weer hoog maakt.
Eerste dataword gaat naar het ene, andere naar het andere display.
(de gekoppelde displays vormen eigenlijk een 32 bits schuifregister)

pic basic code:


Sub Procedure Max_Write()
  latch = 0
  SPI1_Write(Kolom disp1)
  SPI1_Write(Inhoud disp1)
  SPI1_Write(Kolom disp2)
  SPI1_Write(Inhoud disp2)
  latch = 1
end sub

[Bericht gewijzigd door Arco op zondag 3 november 2019 18:31:18 (30%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Maar nu krijg ik nog steeds hetzelfde effect; de waarde van Display1 wordt automatisch doorgeschoven naar Display2. (na 16,5 klokpuls).

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Dat moet toch ook? (je moet natuurlijk wel verschillende data naar de twee displays sturen)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Bavelt

Golden Member

Er komt schot in de zaak. Het is wel even uittekenen wat er precies gebeurt.
Je stopt als het ware de waarde die je in display 2 wilt hebben eerst in Display1 en schuift het dan door..

Even iets anders:

pic basic code:

 latch = 1 

Deze pin wordt op 0 en 1 gezet. Maar ik had geleerd dat je waardes alleen mag zetten als je de poort als input hebt gedefinieerd.
Toch staat deze op output.

Maar dan kreeg je toch 'ruzie' met de output driver als je die naar beneden wordt getrokken?

Fouten zijn het bewijs dat je het probeert..
Arco

Special Member

Een output moet je toch juist hoog of laag zetten? (met een input gaat dat zeker niet)
Alle displaysdrivers worden 1 lang schuifregister. Als je er 4 in serie zet moet je dus 64 bits shiften...

[Bericht gewijzigd door Arco op zondag 3 november 2019 23:49:05 (39%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com