Anbei die SPI.
Das ist eigentlich eine Ansteuerung für ein GLCD (DOGS 102), die
verwendet aber die SPI des PIC.
Die initfunktion ist:
1 | void init_hardware(uint8_t g_enable)
|
2 | {
|
3 | if(g_enable == 1)
|
4 | {
|
5 | //switch power on
|
6 | oDISP_POWER = 0;
|
7 | tDISP_POWER = 0;
|
8 |
|
9 | //Special function pins
|
10 | oDISP_NRST = 0; //set display in reset
|
11 | tDISP_NRST = 0;
|
12 | oDISP_CD = 0; //default : command
|
13 | tDISP_CD = 0;
|
14 | //SPI
|
15 | oDISP_NCSN = 0;
|
16 | tDISP_NCSN = 0;
|
17 | oDISP_SCK = 0;
|
18 | tDISP_NCSN = 0;
|
19 | oDISP_MOSI = 0;
|
20 | tDISP_MOSI = 0; //INOUT : default is OUT
|
21 |
|
22 | /*initialize SPI*/
|
23 | //attach remappable pins to SPI module
|
24 | //RPINR20bits.SDI1R = 21; //RP21 = oDISP_MOSI (BIDIR)
|
25 | OSCCON = 0x46;
|
26 | OSCCON = 0x57; //unlock sequence 46,57
|
27 | OSCCONbits.IOLOCK = 0;
|
28 | RPOR14bits.RP28R = 8; //RP19 = oDISP_SCK (Clockout) RB4 RP28
|
29 | RPOR9bits.RP18R = 7; //RP21 = oDISP_MOSI (BIDIR RB5 RP18
|
30 | OSCCONbits.IOLOCK = 1;
|
31 | //RPOR13bits.RP26R = 9; //RP26 = oDISP_NCSN (chipselect)
|
32 |
|
33 |
|
34 | //init SPI module : no Interrupt, 8MHz SPI clock
|
35 | SPI1CON1 = SPI1CON2 = 0;
|
36 | SPI1CON1bits.DISSCK = 0; //SPI clock Enable
|
37 | SPI1CON1bits.DISSDO = 0; //SPI data out enable
|
38 | SPI1CON1bits.MODE16 = 0; //bytewise communication
|
39 | SPI1CON1bits.SMP = 0;
|
40 | SPI1CON1bits.CKE = 0;
|
41 | SPI1CON1bits.SSEN = 0;
|
42 | SPI1CON1bits.CKP = 1; //clock is active low
|
43 | SPI1CON1bits.MSTEN = 1; //master mode
|
44 | SPI1CON1bits.SPRE = 0b111;//Secondary Clock Prescale 1:1
|
45 | SPI1CON1bits.PPRE = 0b11; //Primary Prescaler 1:1
|
46 | //--> SPI-Clock = 8MHz
|
47 | SPI1CON2bits.FRMEN = 0; //Framed SPI Support disabled
|
48 | SPI1CON2bits.SPIFSD = 0; //Framed SPI pulse output
|
49 | SPI1CON2bits.SPIFPOL = 0; //Frame Sync Pulse output
|
50 | SPI1CON2bits.SPIFE = 0; //Frame Sync Pulse Polarity active low
|
51 | SPI1CON2bits.SPIBEN = 1; //Enhanced Buffer Mode Disabled
|
52 |
|
53 | SPI1STATbits.SPIROV = 0; //Overflow Flag rücksetzen
|
54 | SPI1STATbits.SPIEN = 1; //SPI-Modul 1 Enable
|
55 | SPI1STATbits.SISEL = 0b100; //Interrupt, if TX FIFO is writable
|
56 | }
|
57 | else
|
58 | {
|
59 | SPI1STATbits.SPIEN = 0; //SPI-Modul 1 Enable
|
60 | SPI1CON1 = SPI1CON2 = 0;
|
61 |
|
62 | //switch all to out and drive Low
|
63 | tDISP_NRST = oDISP_NRST = 0;
|
64 | tDISP_NCSN = oDISP_NCSN = 0;
|
65 | tDISP_MOSI = oDISP_MOSI = 0;
|
66 | tDISP_CD = oDISP_CD = 0;
|
67 | tDISP_SCK = oDISP_SCK = 0;
|
68 | //switch power off
|
69 | oDISP_POWER = 1;
|
70 | }
|
71 | }
|
SPI-Transfer ist:
1 | inline uint8_t SPI_WRITE(uint8_t IN)
|
2 | {
|
3 | SPI1BUF = IN; // write to buffer for TX
|
4 | while(SPI1STATbits.SPITBF);// wait for transfer to complete
|
5 | return SPI1BUF; // read the received value
|
6 | }//writeSPI2
|
ACHTUNG: Chipselect wird hier nicht bedient, das müsste man eventuell
dazutun.
So wie das jetzt konfiguriert ist, ist es mit glaube ich 8MHz
SPI-Frequenz - kein Teiler. Weil das RAM des Display < 1kByte groß ist,
habe ich mich nicht mit Interrupts oder DMA gequält - mit 8MHz geht das
auch so schnell genug.
Ich hätte ein Beispiel mit DMA allerdings auch noch herumfliegen...
Einschränkend muss ich sagen, dass ich noch nie auch nur ein einzelnes
Bit vom Display gelesen habe, funktionieren sollte es aber. Das
Schreiben geht aber sicher.