Announcement: there is an
English version of this forum on
EmbDev.net . Posts you create there will be displayed on Mikrocontroller.net
and EmbDev.net.
ich versuche gerade, eine 7 Segment Indicator (siehe Bild), die von
einem MAX7219 gesteuert wird, mit einem STM32F303 via Software SPI
anzusteuern.
Aber klappt etwas nicht!
1
2 /**
3 ******************************************************************************
4 * @file main.c
5 * @author Ac6
6 * @version V1.0
7 * @date 01-December-2013
8 * @brief Default main function.
9 ******************************************************************************
10 */
11
12 #include "stm32f30x.h"
13 #include "stm32f30x_gpio.h"
14 #include "stm32f30x_rcc.h"
15 #include "stm32f30x_spi.h"
16
17 #define SCK_Pin GPIO_Pin_10
18 #define SCK_Pin_Port GPIOC
19
20 #define MOSI_Pin GPIO_Pin_12
21 #define MOSI_Pin_Port GPIOC
22
23 #define SS_Pin GPIO_Pin_2
24 #define SS_Pin_Port GPIOD
25
26 #define cs_set() SS_Pin_Port->BRR = SS_Pin;
27 #define cs_reset() SS_Pin_Port->BSRR = SS_Pin;
28
29 //OPTIONS
30 #define SCANLIMIT 7
31 #define INTENSITY_HIGH 12
32 #define INTENSITY_MED 7
33 #define INTENSITY_LOW 3
34 #define DP 0x80
35 #define MINUS 0x0a
36 #define BLANK 0x0f
37 #define DECODEMODE 0xff
38
39 //OPCODES
40 #define OP_NOOP 0
41 #define OP_DIGIT0 1
42 #define OP_DIGIT1 2
43 #define OP_DIGIT2 3
44 #define OP_DIGIT3 4
45 #define OP_DIGIT4 5
46 #define OP_DIGIT5 6
47 #define OP_DIGIT6 7
48 #define OP_DIGIT7 8
49 #define OP_DECODEMODE 9
50 #define OP_INTENSITY 10
51 #define OP_SCANLIMIT 11
52 #define OP_SHUTDOWN 12
53 #define OP_DISPLAYTEST 15
54
55 void SPISend ( uint8_t addr , uint8_t data ) {
56 cs_set ()
57 ;
58 SPI_I2S_SendData16 ( SPI3 , ((( uint16_t ) addr << 8 ) + data ));
59 cs_reset ()
60 ;
61
62 }
63
64 void SPIInit ( void ) {
65
66 SPI_InitTypeDef SPIConf ;
67 SPIConf . SPI_Direction = SPI_Direction_2Lines_FullDuplex ;
68 SPIConf . SPI_Mode = SPI_Mode_Master ;
69 SPIConf . SPI_DataSize = SPI_DataSize_8b ;
70 SPIConf . SPI_CRCPolynomial = 7 ;
71 SPIConf . SPI_CPOL = SPI_CPOL_Low ;
72 SPIConf . SPI_CPHA = SPI_CPHA_1Edge ;
73 SPIConf . SPI_NSS = SPI_NSS_Soft ;
74 SPIConf . SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8 ;
75 SPIConf . SPI_FirstBit = SPI_FirstBit_MSB ;
76 SPI_Init ( SPI3 , & SPIConf );
77 SPI_Cmd ( SPI3 , ENABLE );
78 }
79
80 void GPIOInit ( void ) {
81 RCC_AHBPeriphClockCmd (
82 RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD | RCC_APB1ENR_SPI3EN , ENABLE );
83 GPIO_InitTypeDef PORT ;
84
85 PORT . GPIO_Pin = GPIO_Pin_10 ;
86 PORT . GPIO_Speed = GPIO_Speed_2MHz ;
87 PORT . GPIO_Mode = GPIO_Mode_AF ;
88 GPIO_Init ( GPIOC , & PORT );
89
90 PORT . GPIO_Pin = GPIO_Pin_12 ;
91 PORT . GPIO_Speed = GPIO_Speed_2MHz ;
92 PORT . GPIO_Mode = GPIO_Mode_AF ;
93 GPIO_Init ( GPIOC , & PORT );
94
95 PORT . GPIO_Pin = GPIO_Pin_2 ;
96 PORT . GPIO_Speed = GPIO_Speed_2MHz ;
97 PORT . GPIO_Mode = GPIO_Mode_OUT ;
98 GPIO_Init ( GPIOD , & PORT );
99 }
100
101 int main () {
102 SystemInit ();
103 GPIOInit ();
104 SPIInit ();
105 for (;;) {
106 SPISend ( OP_DISPLAYTEST , 0 );
107 SPISend ( OP_SHUTDOWN , 1 );
108
109
110 SPISend ( OP_DECODEMODE , DECODEMODE );
111 SPISend ( OP_DIGIT0 , 7 + DP );
112 SPISend ( OP_DIGIT1 , 6 );
113 SPISend ( OP_DIGIT2 , 5 + DP );
114 SPISend ( OP_DIGIT3 , 4 );
115 SPISend ( OP_DIGIT4 , 3 + DP );
116 SPISend ( OP_DIGIT5 , 2 );
117 SPISend ( OP_DIGIT6 , 1 + DP );
118 SPISend ( OP_DIGIT7 , 0 );
119 }
120 }
MOD: bitte Bedienungsanleitung ab "Wichtige Regeln - erst lesen, dann
posten!" lesen und [c] Tags verwenden.
26.03.2019 11:07 :
Bearbeitet durch Moderator
von
:-) (Gast)
25.03.2019 20:57
ich benutze zwar keinen STM32F...
aber den MAX7219 an PIC Controllern in Assembler.
Damit er da funktioniert muss ich den Serial Port am PIC so einstellen,
dass mit steigender Clockflanke gesendet wird und die Clockpolarität
auf: Clock Idle State high.
Bei dir dürfte das CPOL (Clock Polarity) und CPHA (Clock Phase) sein.
Bei dem Code sehe ich nicht wie T_CSW oder T_CSS eingehalten werden
soll.
Logic high input voltage von mindestens 3,5V sprechen auch eher gegen
einen STM32 , der nur 3,3V VCC verträgt. Da müsste ein Pegelwandler
zwischen, falls der STM keine mit 5V befeuerten I/Os hat.
> via Software SPI
Ich sehe da nur Hardware SPI Zugriffe.
von
SchaumSchläger (Gast)
26.03.2019 10:52
Jim M. schrieb:
> Ich sehe da nur Hardware SPI Zugriffe.
Also alles in allem betrachtet eine rundum durchdachte Lösung.
von
OhWeia (Gast)
26.03.2019 12:11
Das habe ich vor ein paar Tagen im Netz gefunden. Soft-SPI und ging auf
anhieb.
1 void max7219_brightness ( char brightness ) {
2 brightness &= 0x0f ; // mask off extra bits
3 max7219_write_reg ( REG_INTENSITY , brightness ); // set brightness
4
5 }
6
7 void max7219_write_reg ( unsigned char reg_number , unsigned char dataout ) {
8 gpio_clear ( LOAD_PORT , LOAD_PIN );
9 max7219_send_byte ( reg_number ); // write register number to MAX7219
10 max7219_send_byte ( dataout ); // write data to MAX7219
11 gpio_set ( LOAD_PORT , LOAD_PIN );
12 }
13
14 void max7219_send_byte ( unsigned char dataout ) {
15 char i ;
16 for ( i = 8 ; i > 0 ; i -- ) {
17 unsigned char mask = 1 << ( i - 1 ); // calculate bitmask
18 gpio_clear ( CLK_PORT , CLK_PIN );
19 if ( dataout & mask ) // output one data bit
20 gpio_set ( DATA_PORT , DATA_PIN );
21 else // or
22 gpio_clear ( DATA_PORT , DATA_PIN );
23 gpio_set ( CLK_PORT , CLK_PIN );
24 }
25 }
26
27 void init_max7219 ( void ) {
28 rcc_periph_clock_enable ( RCC_GPIOB ); // TODO: RCC_xxxx aus PORT erzeugen
29
30
31 gpio_set_mode ( GPIOB , GPIO_MODE_OUTPUT_2_MHZ , GPIO_CNF_OUTPUT_PUSHPULL , GPIO12 );
32 gpio_set_mode ( GPIOB , GPIO_MODE_OUTPUT_2_MHZ , GPIO_CNF_OUTPUT_PUSHPULL , GPIO13 );
33 gpio_set_mode ( GPIOB , GPIO_MODE_OUTPUT_2_MHZ , GPIO_CNF_OUTPUT_PUSHPULL , GPIO15 );
34
35 max7219_write_reg ( REG_SCAN_LIMIT , 7 ); // set up to scan all eight digits
36 max7219_write_reg ( REG_DECODE , 0x00 ); // set to "no decode" for all digits
37 max7219_write_reg ( REG_SHUTDOWN , 1 ); // put MAX7219 into "normal" mode
38 max7219_write_reg ( REG_DISPLAY_TEST , 0 ); // put MAX7219 into "normal" mode
39
40 max7219_brightness ( 0x00 );
41
42 }
von
OhWeia (Gast)
26.03.2019 12:12
Header vergessen. 1 #define DATA_PORT GPIOB // assume "DATA" is on PA7
2 #define DATA_PIN GPIO15
3 #define CLK_PORT GPIOB // assume "CLK" is on PA5
4 #define CLK_PIN GPIO13
5 #define LOAD_PORT GPIOB // assume "LOAD (nCS)" is on PA6
6 #define LOAD_PIN GPIO12
7
8 #define REG_NOP 0x00 // Nop for daisy chaining
9 #define REG_DIGIT0 0x01
10 #define REG_DIGIT1 0x02
11 #define REG_DIGIT2 0x03
12 #define REG_DIGIT3 0x04
13 #define REG_DIGIT4 0x05
14 #define REG_DIGIT5 0x06
15 #define REG_DIGIT6 0x07
16 #define REG_DIGIT7 0x08
17 #define REG_DECODE 0x09 // "decode mode" register
18 #define REG_INTENSITY 0x0a // "intensity" register
19 #define REG_SCAN_LIMIT 0x0b // "scan limit" register
20 #define REG_SHUTDOWN 0x0c // "shutdown" register
21 #define REG_DISPLAY_TEST 0x0f // "display test" register
Alles klappt. In main() nicht vergessen zwei Funktion zu schreiben
Init_SPI();Init_7219(); Dann einfach schreibt: Send_7219(1,1); erste
Ziffer bedeutet stelle zweite genaue welche ziffer. Quellcode: 1 #include "max7219.h"
2 #include "stm32f30x.h"
3 #include "stm32f30x_gpio.h"
4 #include "stm32f30x_rcc.h"
5 #include "stm32f30x_spi.h"
6
7 #define cs_ON() GPIO_ResetBits(GPIOD, GPIO_Pin_2);
8 #define cs_OFF() GPIO_SetBits(GPIOD, GPIO_Pin_2);
9
10 char dg = 8 ;
11
12 void Init_SPI ( void ) {
13
14 RCC_AHBPeriphClockCmd ( RCC_AHBPeriph_GPIOA , ENABLE );
15 RCC_AHBPeriphClockCmd ( RCC_AHBPeriph_GPIOB , ENABLE );
16 RCC_AHBPeriphClockCmd ( RCC_AHBPeriph_GPIOC , ENABLE );
17 RCC_AHBPeriphClockCmd ( RCC_AHBPeriph_GPIOD , ENABLE );
18 RCC_APB1PeriphClockCmd ( RCC_APB1Periph_SPI3 , ENABLE );
19
20 GPIO_InitTypeDef PORT ;
21 PORT . GPIO_Pin = GPIO_Pin_10 ; //10:SCK->CLK
22 PORT . GPIO_Speed = GPIO_Speed_Level_1 ;
23 PORT . GPIO_Mode = GPIO_Mode_AF ;
24 PORT . GPIO_OType = GPIO_OType_PP ;
25 PORT . GPIO_PuPd = GPIO_PuPd_NOPULL ;
26 GPIO_Init ( GPIOC , & PORT );
27 GPIO_PinAFConfig ( GPIOC , GPIO_PinSource10 , GPIO_AF_6 );
28
29 PORT . GPIO_Pin = GPIO_Pin_12 ; // 12:MOSI->DIN
30 PORT . GPIO_Speed = GPIO_Speed_Level_1 ;
31 PORT . GPIO_Mode = GPIO_Mode_AF ;
32 PORT . GPIO_OType = GPIO_OType_PP ;
33 PORT . GPIO_PuPd = GPIO_PuPd_NOPULL ;
34 GPIO_Init ( GPIOC , & PORT );
35 GPIO_PinAFConfig ( GPIOC , GPIO_PinSource12 , GPIO_AF_6 );
36
37 PORT . GPIO_Pin = GPIO_Pin_2 ; // SS->CS
38 PORT . GPIO_Speed = GPIO_Speed_Level_1 ;
39 PORT . GPIO_Mode = GPIO_Mode_OUT ;
40 PORT . GPIO_OType = GPIO_OType_PP ;
41 GPIO_Init ( GPIOD , & PORT );
42 GPIO_SetBits ( GPIOD , GPIO_Pin_2 );
43
44
45 SPI_InitTypeDef SPIConf ;
46 SPIConf . SPI_Direction = SPI_Direction_1Line_Tx ;
47 SPIConf . SPI_Mode = SPI_Mode_Master ;
48 SPIConf . SPI_DataSize = SPI_DataSize_16b ;
49 //SPIConf.SPI_CRCPolynomial = 7;
50 SPIConf . SPI_CPOL = SPI_CPOL_Low ;
51 SPIConf . SPI_CPHA = SPI_CPHA_1Edge ;
52 SPIConf . SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set ;
53 SPIConf . SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4 ;
54 SPIConf . SPI_FirstBit = SPI_FirstBit_MSB ;
55 SPI_Init ( SPI3 , & SPIConf );
56 SPI_Cmd ( SPI3 , ENABLE );
57 SPI_NSSInternalSoftwareConfig ( SPI3 , SPI_NSS_Soft );
58 }
59
60 //------------------------------------------------------
61
62 void Send_7219 ( uint8_t rg , uint8_t dt ) {
63 cs_ON ()
64 ;
65 while ( SPI_I2S_GetFlagStatus ( SPI3 , SPI_I2S_FLAG_TXE ) == RESET )
66 ;
67 SPI_I2S_SendData16 ( SPI3 , ((( uint16_t ) rg << 8 ) + dt ));
68 while ( SPI_I2S_GetFlagStatus ( SPI3 , SPI_I2S_FLAG_BSY ) == SET )
69 ;
70 cs_OFF ()
71 ;
72 }
73
74 void Clear_7219 ( void ) {
75
76 Send_7219 ( 0x01 , 0x00 );
77 Send_7219 ( 0x02 , 0x00 );
78 Send_7219 ( 0x03 , 0x00 );
79 Send_7219 ( 0x04 , 0x00 );
80 }
81
82 void Number_7219 ( volatile long n ) {
83 uint8_t ng = 0 ;
84 if ( n < 0 ) {
85 ng = 1 ;
86 n *= - 1 ;
87 }
88 uint8_t i = 0 ;
89 do {
90 Send_7219 ( ++ i , n % 10 );
91 n /= 10 ;
92 } while ( n );
93 if ( ng ) {
94 Send_7219 ( i + 1 , 0x0A );
95 }
96 }
97
98 void Init_7219 ( void ) {
99 Send_7219 ( 0x0F , 0x00 );
100 Send_7219 ( 0x0C , 0x01 );
101 Send_7219 ( 0x0B , 0x03 );
102 Send_7219 ( 0x0A , 0x0A );
103 Send_7219 ( 0x09 , 0xFF );
104 Clear_7219 ();
105 }
106
107 void delay ( uint32_t us ) {
108 volatile uint32_t nCount ;
109 RCC_ClocksTypeDef RCC_Clocks ;
110 RCC_GetClocksFreq ( & RCC_Clocks );
111 nCount = ( RCC_Clocks . HCLK_Frequency / 7200 ) * us ;
112 for (; nCount != 0 ; nCount -- )
113 ;
114 }
14.06.2019 06:23 :
Bearbeitet durch Moderator
von
Christian J. (Gast)
06.10.2019 17:11
Hi,
ic bin seit 6h an dem gleichen Problem dran. Diese LED Matrizzen mit 8x8
und nichts klappt am STM32103. Ja, es tut sich was aber nur Müll. Daten
laufen richtig raus, am LA geprüft. Aber es reagieren immer mehrere der
kaskadierten Matrizzen. Nicht mal nacheinander liegen die. Habe 12 in
Reihe geschaltet. Gibt es als 4er Blocks zu kaufen. Auch eine tut es
nicht allein.
Ist das sicher, dass der Max719 auch mit 3.3V noch "haarscharf"
schaltet? Gibt ja auch ESP8266 Videos, wo er es tut. Wenn er es nicht
tut verstehe ich den zufälligen Müll schon eher.
8 und 16 Bit ausprobiert, beides geht aber wohl. Das Durchschieben lasse
ich erstmal weg, nur dass 1 Display erstmal läuft, das erste vorne.
1 /* Die SPI einstellen: Master, 1 Line TX, 8 Bit, Mode 0 */
2 SPI_StructInit ( & SPI_InitStruct );
3 SPI_InitStruct . SPI_Direction = SPI_Direction_1Line_Tx ;
4 SPI_InitStruct . SPI_Mode = SPI_Mode_Master ;
5 SPI_InitStruct . SPI_DataSize = SPI_DataSize_8b ;
6 SPI_InitStruct . SPI_CPOL = SPI_CPOL_Low ;
7 SPI_InitStruct . SPI_CPHA = SPI_CPHA_1Edge ;
8 SPI_InitStruct . SPI_NSS = SPI_NSS_Soft ;
9 SPI_InitStruct . SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16 ; // 4.5 Mhz
10 SPI_InitStruct . SPI_FirstBit = SPI_FirstBit_MSB ;
11
12 SPI_Init ( MAX_SPI , & SPI_InitStruct );
13 SPI_Cmd ( MAX_SPI , ENABLE );
14 }
15
16 void SendCmd ( uint8_t modul , uint8_t cmd , uint8_t val )
17 {
18 if ( modul > 11 )
19 return ;
20
21 CE_LOW ();
22 SPI_SendByte ( cmd );
23 SPI_SendByte ( val );
24
25 // for (int i = 0; i < modul; i++) {
26 // SPI_SendWord(MAX7219_NOP);
27 // }
28
29 CE_HIGH ();
30
31 }
32
33 /* Init Matrix LED */
34 void InitMatrix ()
35 {
36 int v = 0 ;
37
38 /* Decode Mode ausschalten */
39 SendCmd ( v , MAX7219_DECODE_MODE , 0 );
40 SendCmd ( v , MAX7219_SCAN_LIMIT , 7 );
41 SendCmd ( v , MAX7219_BRIGHTNESS , 2 );
42 SendCmd ( v , MAX7219_SHUTDOWN , 1 );
43 SendCmd ( v , MAX7219_TEST , 0 );
44
45 SendCmd ( v , MAX7219_DIGIT_0 , 6 );
von
John Doe (Gast)
06.10.2019 17:28
Christian J. schrieb:
> Ist das sicher, dass der Max719 auch mit 3.3V noch "haarscharf"
> schaltet? Gibt ja auch ESP8266 Videos, wo er es tut. Wenn er es nicht
> tut verstehe ich den zufälligen Müll schon eher.
Warum gibst Du dem Max nicht einfach eine laut Datenblatt vorgegebene
Spannung und schaust, was passiert?
Bei mir am F446 läuft es übrigens. Heisst aber nix.
von
Christian J. (Gast)
06.10.2019 17:31
John Doe schrieb:
> Warum gibst Du dem Max nicht einfach eine laut Datenblatt vorgegebene
> Spannung und schaust, was passiert?
Weil ich die nicht auf dem Lochraster habe? Und einen 74HCT04 dazubauen
ginge noch aber vorher Klarheit schaffen.
von
Christian J. (Gast)
06.10.2019 19:09
hmm.... ein 7404 ist eingebaut, je 2 Inverter in Reihe für die 3 Kanäle
CS, MOSI und CLK... trotzdem spielt das Teil nicht. Gibt es da noch
einen Kniff? Daten stimmen jedenfalls. Die Muster die ich einspiele
erscheinen in allen 4 Displays gleichzeitig und nicht nur in dem ersten.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.