Forum: Mikrocontroller und Digitale Elektronik Olimex STM32-103STK LCD 8544 über SPI


von U. B. (ub007)


Lesenswert?

Hallo.

Ich versuche seit geraumer Zeit das oben genannte Olimex-Board bzw. das 
daran-hängende LCD-Display PCD 8544 am SPI über STM32CubeIDE zum laufen 
zu bekommen. Dazu benutze ich die HAL-Funktionen von STM32.
Ich hab schon alles versucht aber das LCD-Display läßt sich einfach 
nicht ansprechen.
Irgendwie hab ich so langsam den Eindruck, dass es Timing-Probleme vom 
SPI sind. Als Programmer nütze ich den JLink-EDU. Selbst das im 
LCD-Datasheet aufgeführte Beispiel hab ich programmiert, aber es 
reagiert nicht.
Ich häng mal den Source hier mit rein vielleicht kann mir jemand 
weiterhelfen.

Gruß ub
1
/* USER CODE BEGIN Header */
2
/**
3
  ******************************************************************************
4
  * @file           : main.c
5
  * @brief          : Main program body
6
  ******************************************************************************
7
  * @attention
8
  *
9
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
10
  * All rights reserved.</center></h2>
11
  *
12
  * This software component is licensed by ST under BSD 3-Clause license,
13
  * the "License"; You may not use this file except in compliance with the
14
  * License. You may obtain a copy of the License at:
15
  *                        opensource.org/licenses/BSD-3-Clause
16
  *
17
  ******************************************************************************
18
  */
19
/* USER CODE END Header */
20
21
/* Includes ------------------------------------------------------------------*/
22
#include "main.h"
23
24
/* Private includes ----------------------------------------------------------*/
25
/* USER CODE BEGIN Includes */
26
27
/* USER CODE END Includes */
28
29
/* Private typedef -----------------------------------------------------------*/
30
/* USER CODE BEGIN PTD */
31
32
/* USER CODE END PTD */
33
34
/* Private define ------------------------------------------------------------*/
35
/* USER CODE BEGIN PD */
36
#define LED_PortC       GPIO_PIN_12
37
#define LCD_CS_PortC    GPIO_PIN_10
38
#define LCD_DC_PortB    GPIO_PIN_2
39
#define LCD_Reset_PortC GPIO_PIN_7
40
/* USER CODE END PD */
41
42
/* Private macro -------------------------------------------------------------*/
43
/* USER CODE BEGIN PM */
44
#define LED_On()       GPIOC->BRR  |= LED_PortC
45
#define LED_Off()      GPIOC->BSRR |= LED_PortC
46
47
#define LCD_CS_Hi()    GPIOC->BSRR |= LCD_CS_PortC
48
#define LCD_CS_Lo()    GPIOC->BRR  |= LCD_CS_PortC
49
50
#define LCD_Data()     GPIOB->BSRR |= LCD_DC_PortB
51
#define LCD_Command()  GPIOB->BRR  |= LCD_DC_PortB
52
53
#define LCD_Reset_Lo() GPIOC->BRR  |= LCD_Reset_PortC
54
#define LCD_Reset_Hi() GPIOC->BSRR |= LCD_Reset_PortC
55
56
// Display Function Set = 0 0 1 0 0 PD V H
57
// PD=PowerDown 0=Chip active - 1=CHip in PowerDown
58
// V=Vertical-Mode 0=Horizontal-Adressing - 1=Vertical Adressing
59
// H=0 Basic Instruction H=1 Extended Instruction
60
// => PD=0 V=0 H=0    => 0010 0000 = 0x20
61
#define Disp_FunctionSet 0x20
62
#define Disp_FunctionSet_H 0x21
63
64
//      BankX = 0 1 0 0 0 Y2 Y1 Y0
65
#define Bank0 0x40
66
#define Bank1 0x41
67
#define Bank2 0x42
68
#define Bank3 0x43
69
#define Bank4 0x44
70
#define Bank5 0x45
71
72
// Display-Control bei DC=0=Command    0000 1D0E
73
// und H=0
74
// Blank               D=0 E=0       = 0000 1000 = 0x08
75
// Normal-Mode         D=1 E=0       = 0000 1100 = 0x0C
76
// All-Displaysegments D=0 E=1       = 0000 1001 = 0x09
77
// Invers              D=1 E=1       = 0000 1101 = 0x0D
78
#define Disp_Ctrl_Blank 0x08
79
#define Disp_Ctrl_Norm  0x0C
80
#define Disp_Ctrl_All   0x09
81
#define Disp_Ctrl_Inv   0x0D
82
83
/* USER CODE END PM */
84
85
/* Private variables ---------------------------------------------------------*/
86
SPI_HandleTypeDef hspi1;
87
88
/* USER CODE BEGIN PV */
89
HAL_StatusTypeDef spi1_status;
90
/* USER CODE END PV */
91
92
/* Private function prototypes -----------------------------------------------*/
93
void SystemClock_Config(void);
94
static void MX_GPIO_Init(void);
95
static void MX_SPI1_Init(void);
96
97
/* USER CODE BEGIN PFP */
98
void myDelay(unsigned long delay);
99
void LCD_Reset(void);
100
void Test_LCD(void);
101
void Write_Data(uint8_t v);
102
/* USER CODE END PFP */
103
104
/* Private user code ---------------------------------------------------------*/
105
/* USER CODE BEGIN 0 */
106
107
/* USER CODE END 0 */
108
109
/**
110
  * @brief  The application entry point.
111
  * @retval int
112
  */
113
int main(void)
114
{
115
  /* USER CODE BEGIN 1 */
116
117
  /* USER CODE END 1 */
118
119
  /* MCU Configuration--------------------------------------------------------*/
120
121
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
122
  // Schön wärs, aber dann läuft der Debugger nich...
123
  // auskommentiert und damit gehts weiter.
124
  //HAL_Init();
125
126
  /* USER CODE BEGIN Init */
127
128
  /* USER CODE END Init */
129
130
  /* Configure the system clock */
131
  SystemClock_Config();
132
133
  /* USER CODE BEGIN SysInit */
134
135
  /* USER CODE END SysInit */
136
137
  /* Initialize all configured peripherals */
138
  MX_GPIO_Init();
139
  MX_SPI1_Init();
140
141
  /* USER CODE BEGIN 2 */
142
  uint8_t k=0,k1=0;
143
  LCD_Reset();
144
  LCD_CS_Hi();              // CS auf High damit LCD deaktiviert
145
  Test_LCD();
146
  LED_Off();
147
  /* USER CODE END 2 */
148
149
  /* Infinite loop */
150
  /* USER CODE BEGIN WHILE */
151
  LCD_Data();      //D/C = High => Data
152
153
  while (1)
154
  {
155
    /* USER CODE BEGIN 3 */
156
    LED_Off();
157
    myDelay(500000);
158
    LED_On();
159
    myDelay(500000);
160
    k+=1;
161
    if (k >= 0x1F) { k = 0; }
162
    k1 = k & 0x1F;     // vordere 3 Bits ausblenden sonst inverse Darstellung
163
    //k1=0x1F;
164
    Write_Data(k1);
165
166
    /* USER CODE END 3 */
167
  }
168
  /* USER CODE END WHILE */
169
}
170
171
/**
172
  * @brief System Clock Configuration
173
  * @retval None
174
  */
175
void SystemClock_Config(void)
176
{
177
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
178
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
179
180
  /** Initializes the CPU, AHB and APB busses clocks 
181
  */
182
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
183
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
184
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
185
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
186
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
187
  {
188
    Error_Handler();
189
  }
190
  /** Initializes the CPU, AHB and APB busses clocks 
191
  */
192
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
193
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
194
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
195
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
196
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
197
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
198
199
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
200
  {
201
    Error_Handler();
202
  }
203
}
204
205
/**
206
  * @brief SPI1 Initialization Function
207
  * @param None
208
  * @retval None
209
  */
210
static void MX_SPI1_Init(void)
211
{
212
213
  /* USER CODE BEGIN SPI1_Init 0 */
214
215
  /* USER CODE END SPI1_Init 0 */
216
217
  /* USER CODE BEGIN SPI1_Init 1 */
218
219
  /* USER CODE END SPI1_Init 1 */
220
  /* SPI1 parameter configuration*/
221
  hspi1.Instance = SPI1;
222
  hspi1.Init.Mode = SPI_MODE_MASTER;
223
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
224
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
225
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
226
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
227
  hspi1.Init.NSS = SPI_NSS_SOFT;
228
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
229
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
230
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
231
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
232
  hspi1.Init.CRCPolynomial = 7;
233
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
234
  {
235
    Error_Handler();
236
  }
237
  /* USER CODE BEGIN SPI1_Init 2 */
238
239
  /* USER CODE END SPI1_Init 2 */
240
241
}
242
243
/**
244
  * @brief GPIO Initialization Function
245
  * @param None
246
  * @retval None
247
  */
248
static void MX_GPIO_Init(void)
249
{
250
  GPIO_InitTypeDef GPIO_InitStruct = {0};
251
252
  /* GPIO Ports Clock Enable */
253
  __HAL_RCC_GPIOA_CLK_ENABLE();
254
  __HAL_RCC_GPIOB_CLK_ENABLE();
255
  __HAL_RCC_GPIOC_CLK_ENABLE();
256
257
  /*Configure GPIO pin Output Level */
258
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
259
260
  /*Configure GPIO pin Output Level */
261
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_12, GPIO_PIN_RESET);
262
263
  /*Configure GPIO pin : PB2 */
264
  GPIO_InitStruct.Pin = GPIO_PIN_2;
265
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
266
  GPIO_InitStruct.Pull = GPIO_NOPULL;
267
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
268
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
269
270
  /*Configure GPIO pins : PC7 PC10 PC12 */
271
  GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_12;
272
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
273
  GPIO_InitStruct.Pull = GPIO_NOPULL;
274
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
275
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
276
277
  /*Configure GPIO pin : PA5 PA7  war nicht notwendig LCD geht trotzdem nicht*/
278
  GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_7;
279
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
280
  //GPIO_InitStruct.Pull = GPIO_NOPULL;
281
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
282
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
283
  //GPIO_PinRemapConfig(GPIO_Remap_SPI1, DISABLE);
284
}
285
286
/* USER CODE BEGIN 4 */
287
/**-------------------------------------------------------------------------
288
  * @brief  This function is to delay some seconds.
289
  * @retval None
290
  * ------------------------------------------------------------------------
291
  */
292
void myDelay(unsigned long delay)
293
{
294
   while(delay)
295
   {
296
      delay=delay-1;
297
      if (delay == 0) break;
298
      asm volatile ("nop");
299
   }
300
}
301
302
void LCD_Reset(void)
303
{
304
    LCD_CS_Lo();             // Enable auf High damit LCD aktiviert
305
    LCD_Reset_Lo();
306
    myDelay(10000);          // RST f. 10us auf Low dann wieder High
307
    LCD_Reset_Hi();
308
    LCD_CS_Hi();
309
}
310
311
void Test_LCD(void)
312
{
313
    uint8_t k1=0;
314
315
    LCD_Command();    // D/C = Low => Command
316
    Write_Data(Disp_FunctionSet_H);
317
    k1=0x90;
318
    Write_Data(k1);
319
    Write_Data(Disp_FunctionSet);
320
    Write_Data(Disp_Ctrl_Inv);
321
}
322
323
void Write_Data(uint8_t v)
324
{
325
    uint8_t k1=0;
326
    uint32_t timeout=2,error;
327
328
    //PCD8544_CS_L();
329
    //PCD8544_DATA();
330
    //SPI_I2S_SendData(SPI1, Data);
331
    //while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
332
    //PCD8544_CS_H();
333
    LCD_CS_Lo();    // LCD aktivieren
334
    k1 = v;
335
    spi1_status = HAL_SPI_Transmit(&hspi1,&k1,1,timeout);
336
    while(spi1_status == HAL_BUSY);
337
    LCD_CS_Hi();    // LCD deaktivieren
338
    error = HAL_SPI_GetError(&hspi1);
339
    if (error != 0)
340
    {
341
        Error_Handler();
342
    }
343
    myDelay(100);
344
}
345
346
/* USER CODE END 4 */
347
348
/**
349
  * @brief  This function is executed in case of error occurrence.
350
  * @retval None
351
  */
352
void Error_Handler(void)
353
{
354
  /* USER CODE BEGIN Error_Handler_Debug */
355
  /* User can add his own implementation to report the HAL error return state */
356
    int i=1;
357
    for (i=1;i<=5;i++)
358
    {
359
        /* USER CODE BEGIN 3 */
360
        LED_Off();
361
        myDelay(50000);
362
        LED_On();
363
        myDelay(50000);
364
        /* USER CODE END 3 */
365
    }
366
    myDelay(500000);
367
368
  /* USER CODE END Error_Handler_Debug */
369
}
370
371
#ifdef  USE_FULL_ASSERT
372
/**
373
  * @brief  Reports the name of the source file and the source line number
374
  *         where the assert_param error has occurred.
375
  * @param  file: pointer to the source file name
376
  * @param  line: assert_param error line source number
377
  * @retval None
378
  */
379
void assert_failed(uint8_t *file, uint32_t line)
380
{ 
381
  /* USER CODE BEGIN 6 */
382
  /* User can add his own implementation to report the file name and line number,
383
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
384
  /* USER CODE END 6 */
385
}
386
#endif /* USE_FULL_ASSERT */
387
388
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

von Verzwei Felter (Gast)


Angehängte Dateien:

Lesenswert?

U. B. schrieb:
> Ich häng mal den Source hier mit rein vielleicht kann mir jemand
> weiterhelfen.

Aber bitte nicht so.

Eigentlich sollte man annehmen können dass du lesen kannst.
Und den Inhalt entsprechend umsetzen.

von Stefan F. (Gast)


Lesenswert?

> Ich hab schon alles versucht aber das LCD-Display läßt sich
> einfach nicht ansprechen.

Das ist eine Menge Quelltext mit einer noch viel größeren Menge 
Framework dahinter, welches nach meiner Erfahrung oft fehlerhaft ist 
(insbesondere was die STM32F1 Serie angeht).

Aber ich will Dir die HAL nicht madig machen, besser konstruktive 
Ratschläge geben. Das heisst in diesem Fall, Strukturiert vorgehen.

Zuerstmal solltest du mit einem Messgerät (z.B. Logic Analyzer) klären, 
was auf der SPI Schnittstelle passiert. Tut sich überhaupt irgend etwas? 
Und du solltest Unterbrechungspunkte in die Errorhandler setzen um 
nachzuschauen, welche Fehlercodes die HAL meldet. Dann suchst du die 
Erklärungen zu diesen Codes heraus.

Was ist mit deiner LED, blinkt die wenigstens regelmäßig alle 500ms?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.