Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.84/25: Рейтинг темы: голосов - 25, средняя оценка - 4.84
1 / 1 / 0
Регистрация: 22.06.2016
Сообщений: 96

Вывод информации на TFT через SPI

04.12.2018, 08:06. Показов 5808. Ответов 55

Студворк — интернет-сервис помощи студентам
Всем доброго дня. Помогите с выводом информации на TFT-экран (в моем случае на ILI9341 1,8 дюйма). Пример с ногодрыгом нашел, освоил, вывод букв, строк получается. Теперь хотелось бы вывести информацию через SPI2 (SPI1 у меня уже занят под потенциометры АЦП), да и что-то мне подсказывает, что аппаратная реализация будет правильнее.

В коде для отслеживания прописал синий светодиод плюс осциком на выводе PB15 (SPI2_MOSI) вижу сигналы. После инициализации экран немного изменяет цвет и ничего не происходит, хотя должен выводиться небольшой красный квадрат. Может быть в последовательностях CS, DC и RESET ошибся? Либо в SPI2 отправка данных неправильная ...
Инициализация TFT точно рабочая, так как в режиме ногодрыга она актуальна.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
#include "stm32f10x.h"
 
/*PC0 - CS (3), PB10 - RESET (4), PB11 - DC (5), PC1 - LED (8), PB13 - SPI2_SCK (7), PB14 - SPI2_MISO (9), PB15 - SPI2_MOSI(6)----*/
  
// Colors
#define RED     0xf800
#define GREEN       0x07e0
#define BLUE        0x001f
#define BLACK       0x0000
#define YELLOW      0xffe0
#define WHITE       0xffff
#define CYAN        0x07ff
#define BRIGHT_RED  0xf810
#define GRAY1       0x8410
#define GRAY2       0x4208
 
#define CS_LOW           GPIOC->BSRR |= GPIO_BSRR_BR0
#define CS_HIGH          GPIOC->BSRR |= GPIO_BSRR_BS0
 
#define DC_LOW           GPIOB->BSRR |= GPIO_BSRR_BR11
#define DC_HIGH          GPIOB->BSRR |= GPIO_BSRR_BS11
 
#define RESET_LOW        GPIOB->BSRR |= GPIO_BSRR_BR10
#define RESET_HIGH       GPIOB->BSRR |= GPIO_BSRR_BS10
 
 
/*-----------------------------------------------------Тактирование-----------------------------------*/
void RCC_Init () {
  
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);                      // Enable HSE
    while (!(RCC->CR & RCC_CR_HSERDY));                 // Ready start HSE      
    
    FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;          // Cloclk Flash memory
    
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;                    // AHB = SYSCLK/1
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV1;                   // APB1 = HCLK/1
    RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;                   // APB2 = HCLK/1
    
    RCC->CFGR &= ~RCC_CFGR_PLLMULL;                             // clear PLLMULL bits
    RCC->CFGR &= ~RCC_CFGR_PLLSRC;                      // clearn PLLSRC bits
    RCC->CFGR &= ~RCC_CFGR_PLLXTPRE;                    // clearn PLLXTPRE bits
    
    RCC->CFGR |= RCC_CFGR_PLLSRC_PREDIV1;                   // source HSE
    RCC->CFGR |= RCC_CFGR_PLLXTPRE_PREDIV1_Div2;                // source HSE/2 = 4 MHz
    RCC->CFGR |= RCC_CFGR_PLLMULL6;                     // PLL x6: clock = 4 MHz * 6 = 24 MHz
    
    RCC->CR |= RCC_CR_PLLON;                                    // enable PLL
    while((RCC->CR & RCC_CR_PLLRDY) == 0) {}                    // wait till PLL is ready
    
    RCC->CFGR &= ~RCC_CFGR_SW;                                  // clear SW bits
        RCC->CFGR |= RCC_CFGR_SW_PLL;                                   // select source SYSCLK = PLL
    while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_1) {}          // wait till PLL is used
        
        //Тактирование периферии
  
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN;
 
RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; // Тактируем SPI2
 
}
 
 
 
 
/*----------------------------Инициализация ног для светодиодов на отладочной плате---------------------------------*/
 
void GPIO_LEDInit () {
  
   GPIOC->CRH |= GPIO_CRH_MODE8; GPIOC->CRH &= ~GPIO_CRH_CNF8;
   GPIOC->CRH |= GPIO_CRH_MODE9; GPIOC->CRH &= ~GPIO_CRH_CNF9; //Выводы синего и зеленого светодиодов на отладочной плате
  
}
 
 
void Blue_On (int sw) {
  
  if (sw) GPIOC->BSRR |= GPIO_BSRR_BS8;
  else GPIOC->BSRR |= GPIO_BSRR_BR8;
  
};
 
 
 
/*-----------------------------Инициализация ножек SPI2 и TFT---------------------------------------*/
void GPIO_TFTlegs_Init () {
  /*----Смотреть стр.107 RM0041-----*/
/*PC0 - CS (3), PB10 - RESET (4), PB11 - DC (5), PC1 - LED (8), PB13 - SPI2_SCK (7), PB14 - SPI2_MISO (9), PB15 - SPI2_MOSI(6)----*/
  
  GPIOB->CRH &= ~GPIO_CRH_CNF10 & ~GPIO_CRH_CNF11;
  GPIOB->CRH |= GPIO_CRH_MODE10 | GPIO_CRH_MODE11;
  
  GPIOC->CRL |= GPIO_CRL_MODE0; GPIOC->CRL &= ~GPIO_CRL_CNF0;
  GPIOC->CRL |= GPIO_CRL_MODE1; GPIOC->CRL &= ~GPIO_CRL_CNF1; 
  
  //вывод SCK: выход двухтактный, альтернативная функция, 50MHz
GPIOB->CRH   |=  GPIO_CRH_MODE13;    //
GPIOB->CRH   &= ~GPIO_CRH_CNF13;     //
GPIOB->CRH   |=  GPIO_CRH_CNF13_1;   //
 
//вывод MISO: вход цифровой с подтягивающим резистором, подтяжка к плюсу
GPIOB->CRH   &= ~GPIO_CRH_MODE14;    //
GPIOB->CRH   &= ~GPIO_CRH_CNF14;     //
GPIOA->CRH   |=  GPIO_CRH_CNF14_1;   //
GPIOB->BSRR   =  GPIO_BSRR_BS14;     //
 
//вывод MOSI: выход двухтактный, альтернативная функция, 50MHz
GPIOB->CRH   |=  GPIO_CRH_MODE15;    //
GPIOB->CRH   &= ~GPIO_CRH_CNF15;     //
GPIOB->CRH   |=  GPIO_CRH_CNF15_1;   //
     
}
 
 
void Init_SPI2() {
  
  SPI2->CR1 = 0x0000;
  SPI2->CR2 = 0x0000;
  SPI2->CR1 |= SPI_CR1_BR; //fpclk/256 = 24 000 000/256 = 93750
  SPI2->CR1 &= ~SPI_CR1_CPOL;             //Polarity cls signal CPOL = 0;
  SPI2->CR1 &= ~SPI_CR1_CPHA;             //Phase cls signal    CPHA = 0;
  SPI2->CR1 &= ~SPI_CR1_DFF;               //8 bit data
  SPI2->CR1 &= ~SPI_CR1_LSBFIRST; // Ногами вперед
  SPI2->CR1    |= SPI_CR1_SSI;        //обеспечить высокий уровень программного NSS
  SPI2->CR1    |= SPI_CR1_SSM;        //разрешить программное формирование NSS
  SPI2->CR1    |= SPI_CR1_MSTR;       //контроллер должен быть мастером 
  SPI2->CR1    |= SPI_CR1_SPE;        //разрешить работу модуля SPI2
  
}
 
 
 
/*-----------------------------------------------------Отправка байта данных в TFT-----------------------------------------*/
void TFT_SEND_BYTE(int data) {while(!(SPI2->SR & SPI_SR_TXE)); SPI2->DR = data;}
 
/*-----------------------------------------------------Отправка команды в TFT----------------------------------------------*/
void TFT_SEND_CMD(int cmd) {while(SPI2->SR & SPI_SR_BSY); CS_LOW; TFT_SEND_BYTE(cmd);}
 
/*-----------------------------------------------------Отправка данных в TFT-----------------------------------------------*/
void TFT_SEND_DATA(int data) {while(SPI2->SR & SPI_SR_BSY); DC_HIGH; TFT_SEND_BYTE(data);}
 
/*----------------------------------------------------Отправка слова в TFT-------------------------------------------------*/
void TFT_SEND_WORD(int data) {while(SPI2->SR & SPI_SR_BSY); DC_HIGH; TFT_SEND_BYTE(data >> 8); TFT_SEND_BYTE(data & 0x00FF);}
 
 
 
/*-----------------------------------------------------Инициализируем TFT--------------------------------------------------*/
void TFT_INIT()
 
{
  
  GPIO_TFTlegs_Init ();
  Init_SPI2 ();
 
  CS_HIGH;
  RESET_HIGH;
  TFT_SEND_CMD(0x01);
  for (int i=0;i<1000000;i++);
  
   
  //Поехали настраивать  TFT!!!
 TFT_SEND_CMD(0xCB);
    TFT_SEND_DATA(0x39);
    TFT_SEND_DATA(0x2C);
    TFT_SEND_DATA(0x00);
    TFT_SEND_DATA(0x34);
    TFT_SEND_DATA(0x02);
 
  TFT_SEND_CMD(0xCF);
    TFT_SEND_DATA(0x00);
    TFT_SEND_DATA(0xC1);
    TFT_SEND_DATA(0x30);
 
  TFT_SEND_CMD(0xE8);
    TFT_SEND_DATA(0x85);
    TFT_SEND_DATA(0x00);
    TFT_SEND_DATA(0x78);
 
  TFT_SEND_CMD(0xEA);
    TFT_SEND_DATA(0x00);
    TFT_SEND_DATA(0x00);
 
  TFT_SEND_CMD(0xED);
    TFT_SEND_DATA(0x64);
    TFT_SEND_DATA(0x03);
    TFT_SEND_DATA(0x12);
    TFT_SEND_DATA(0x81);
 
  TFT_SEND_CMD(0xF7);
    TFT_SEND_DATA(0x20);
 
  TFT_SEND_CMD(0xC0);       //Power control
    TFT_SEND_DATA(0x23);    //VRH[5:0]
 
  TFT_SEND_CMD(0xC1);       //Power control
    TFT_SEND_DATA(0x10);    //SAP[2:0];BT[3:0]
 
  TFT_SEND_CMD(0xC5);       //VCM control
    TFT_SEND_DATA(0x3E);    //Contrast
    TFT_SEND_DATA(0x28);
 
  TFT_SEND_CMD(0xC7);       //VCM control2
    TFT_SEND_DATA(0x86);     //--
 
  TFT_SEND_CMD(0x36);       // Memory Access Control
    TFT_SEND_DATA(0x48);    //C8       //48 68з»”ж*§зќ†//28 E8 е¦ЇоЃ„зќ†
 
  TFT_SEND_CMD(0x3A);
    TFT_SEND_DATA(0x55);
 
  TFT_SEND_CMD(0xB1);
    TFT_SEND_DATA(0x00);
    TFT_SEND_DATA(0x18);
 
  TFT_SEND_CMD(0xB6);       // Display Function Control
    TFT_SEND_DATA(0x08);
    TFT_SEND_DATA(0x82);
    TFT_SEND_DATA(0x27);
 
  TFT_SEND_CMD(0xF2);       // 3Gamma Function Disable
    TFT_SEND_DATA(0x00);
 
  TFT_SEND_CMD(0x26);       //Gamma curve selected
    TFT_SEND_DATA(0x01);
 
  TFT_SEND_CMD(0xE0);       //Set Gamma
    TFT_SEND_DATA(0x0F);
    TFT_SEND_DATA(0x31);
    TFT_SEND_DATA(0x2B);
    TFT_SEND_DATA(0x0C);
    TFT_SEND_DATA(0x0E);
    TFT_SEND_DATA(0x08);
    TFT_SEND_DATA(0x4E);
    TFT_SEND_DATA(0xF1);
    TFT_SEND_DATA(0x37);
    TFT_SEND_DATA(0x07);
    TFT_SEND_DATA(0x10);
    TFT_SEND_DATA(0x03);
    TFT_SEND_DATA(0x0E);
    TFT_SEND_DATA(0x09);
    TFT_SEND_DATA(0x00);
 
  TFT_SEND_CMD(0xE1);       //Set Gamma
    TFT_SEND_DATA(0x00);
    TFT_SEND_DATA(0x0E);
    TFT_SEND_DATA(0x14);
    TFT_SEND_DATA(0x03);
    TFT_SEND_DATA(0x11);
    TFT_SEND_DATA(0x07);
    TFT_SEND_DATA(0x31);
    TFT_SEND_DATA(0xC1);
    TFT_SEND_DATA(0x48);
    TFT_SEND_DATA(0x08);
    TFT_SEND_DATA(0x0F);
    TFT_SEND_DATA(0x0C);
    TFT_SEND_DATA(0x31);
    TFT_SEND_DATA(0x36);
    TFT_SEND_DATA(0x0F);
 
  TFT_SEND_CMD(0x11);       //Exit Sleep
      for (int i=0;i<1000000; i++);
 
  TFT_SEND_CMD(0x29);    //Display on
  TFT_SEND_CMD(0x2C);
  
  }
 
/*--------------------------------------------------Функция включения/выключения светодиодной подсветки--------------------------*/
void TFT_LED (int tftled){if(tftled) {GPIOC->BSRR |= GPIO_BSRR_BS1;} else GPIOC->BSRR |= GPIO_BSRR_BR1;}
 
/*--------------------------------------------------Установка столбцов-----------------------------------------------------------*/
void TFT_SET_COLUMNS (int STARTcol, int ENDcol) {TFT_SEND_CMD(0x2A); TFT_SEND_WORD(STARTcol); TFT_SEND_WORD(ENDcol);}
 
/*-------------------------------------------------Установка строк---------------------------------------------------------------*/
void TFT_SET_PAGES (int STARTpage, int ENDpage) {TFT_SEND_CMD(0x2B); TFT_SEND_WORD(STARTpage); TFT_SEND_WORD(ENDpage);}
 
/*-------------------------------------------------Оси ХУ------------------------------------------------------------------------*/
void TFT_SET_XY (int poX, int poY) {TFT_SET_COLUMNS(poX, poX); TFT_SET_PAGES(poY, poY); TFT_SEND_CMD(0x2C);}
 
/*-------------------------------------------------Установка группы пикселей-----------------------------------------------------*/
void TFT_SET_PIXELS (int poX, int poY, int color) {TFT_SET_XY(poX, poY); TFT_SEND_WORD(color);}
 
 
 
int main () {
  
    RCC_Init();
    GPIO_LEDInit ();
    
   
  
int i,j;
   
  TFT_INIT();
  TFT_LED(1);
  
  
  for(i=150; i<200; i++) {
        for(j=150; j<200; j++) {
            TFT_SET_PIXELS(i, j, RED);
        }
    }
  
  Blue_On(1);
  
  
while(1);
 
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
04.12.2018, 08:06
Ответы с готовыми решениями:

Вывод кириллических символов на tft ili9341 spi, stm32f103
Доброго времени суток, не получается вывести, а точнее создать базу символов с кириллическими буквами для tft экрана. До этого всегда...

STM32F429-Disco TFT Плывет картинка по SPI
Добрый день Проявился непонятный эффект. Плата STM32F429i-disco с дисплеем на ili9341 режим 4-wire. Работало нормально до того...

Пример работы с tft экраном по spi DMA для hal
Доброго времени суток. Может кто поделится кодом, для работы с tft 320x240 ili9341 по spi с применением DMA (stm32f103)? на HAL...

55
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
12.12.2018, 13:33
Студворк — интернет-сервис помощи студентам
Vozz, у меня вот что получается. Один синус на верхнее плечо, второй на нижнее
1
1 / 1 / 0
Регистрация: 22.06.2016
Сообщений: 96
14.12.2018, 17:25  [ТС]
Теперь понял! Заморочился я немного с каналами, а можно было проще ) Теперь точно проведу рефакторинг .
А все из-за того, что когда-то давно сделал неправильный вывод .

Поолучается я все свои три фазы одним таймером сгенерю.
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
14.12.2018, 17:28
Vozz, именно так) нужно только будет 3 таблички синуса, для каждого канала сдвинутые по фазе друг относительно друга)
0
1 / 1 / 0
Регистрация: 22.06.2016
Сообщений: 96
14.12.2018, 17:32  [ТС]
И все-таки опять вернемся к DMA ...
Упростил до элементарного, абстрагировался от TFT. Теперь задача выслать байт с ноги MOSI и поймать на MISO (перемычка на отладочной плате между PA6 и PA7).

В режиме "чистого" SPI что отправил - то и поймал, вопросов нет. Но через DMA отправляю одно - приходит другое.

К примеру сейчас отправил 0х08 получил 0х65.
С указателями я пока не очень дружу, поэтому в качестве аргументов обычные переменные
0
1 / 1 / 0
Регистрация: 22.06.2016
Сообщений: 96
14.12.2018, 17:36  [ТС]
В рефмане есть что-то вроде карты таймингов. Но не очень понятно ...
Миниатюры
Вывод информации на TFT через SPI  
0
1 / 1 / 0
Регистрация: 22.06.2016
Сообщений: 96
14.12.2018, 17:42  [ТС]
В отладчике видно, что в CMAR3 попадает именно то число, которое я и передаю в функцию передачи байта по DMA, но вот до SPI1->DR видимо уже не все доходит? Флаг GIF, TCIF и HTIF поднимаются
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
14.12.2018, 17:46
Vozz, по какому принципу сейчас отправляете? Если как я писал, то попробуйте в прерывании по завершению передачи подождать установки флага SPI RXNE, а только потом поднимите пин CS
0
1 / 1 / 0
Регистрация: 22.06.2016
Сообщений: 96
14.12.2018, 17:46  [ТС]
Сейчас по SPI+DMA
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
14.12.2018, 17:48
Либо когда флаг BSY в 0 уйдет

Добавлено через 43 секунды
Vozz, киньте лучше код, которым сейчас оперируете
0
1 / 1 / 0
Регистрация: 22.06.2016
Сообщений: 96
14.12.2018, 17:49  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include "stm32f10x.h"
#include "stm32f10x_conf.h"
 
 
void DMA1_Channel3_IRQHandler(void) {
    if (DMA1->ISR & DMA_ISR_TCIF3) {
        DMA1_Channel3->CCR &= ~DMA_CCR3_EN; 
        DMA1->IFCR |= DMA_IFCR_CTCIF3;
    }
}
 
 
 
void ALLpins_init () { 
  
  //PA0 - CS(3),PA1-DC(5), PA2 - RST(4),PA3 - LED, PA5 _SCK(7),PA6 - MISO(9),PA7 - MOSI(6)
  
GPIOC->CRL &= ~GPIO_CRL_CNF0;    GPIOC->CRL &= ~GPIO_CRL_CNF1;
GPIOC->CRL |= GPIO_CRL_MODE0;    GPIOC->CRL |= GPIO_CRL_MODE1;
 
GPIOC->CRH &= ~GPIO_CRH_CNF8;    GPIOC->CRH &= ~GPIO_CRH_CNF9;
GPIOC->CRH |= GPIO_CRH_MODE8;    GPIOC->CRH |= GPIO_CRH_MODE9;
   
GPIOA->CRL &= ~GPIO_CRL_CNF2;    GPIOA->CRL &= ~GPIO_CRL_CNF3;
GPIOA->CRL |= GPIO_CRL_MODE2;    GPIOA->CRL |= GPIO_CRL_MODE3;
 
 
   
     //вывод SCK: выход двухтактный, альтернативная функция, 50MHz
GPIOA->CRL   |=  GPIO_CRL_MODE5; GPIOA->CRL   &= ~GPIO_CRL_CNF5; GPIOA->CRL   |=  GPIO_CRL_CNF5_1;   
 
//вывод MISO: вход цифровой с подтягивающим резистором, подтяжка к плюсу
GPIOA->CRL   &= ~GPIO_CRL_MODE6; GPIOA->CRL   &= ~GPIO_CRL_CNF6; GPIOA->CRL   |=  GPIO_CRL_CNF6_1; GPIOA->BSRR   =  GPIO_BSRR_BS6;     
 
//вывод MOSI: выход двухтактный, альтернативная функция, 50MHz
GPIOA->CRL   |=  GPIO_CRL_MODE7; GPIOA->CRL   &= ~GPIO_CRL_CNF7; GPIOA->CRL   |=  GPIO_CRL_CNF7_1;   
 
}
 
 
void Tx_DMA_Ch3 () { 
  
   RCC->AHBENR |= RCC_AHBENR_DMA1EN;
   
   DMA1_Channel3->CCR |= DMA_CCR3_TCIE;//Разрешили прерывание после передачи 
   NVIC_EnableIRQ(DMA1_Channel3_IRQn); //общее разрешение прерываний
   
    SPI1->CR2 |= SPI_CR2_TXDMAEN;
  
}
 
 
void SPI_inint ()  {
  
  RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
  SPI1->CR1 &= ~SPI_CR1_BIDIMODE;
  SPI1->CR1 &= ~SPI_CR1_BIDIOE;
  SPI1->CR1    |= SPI_CR1_MSTR;       //контроллер должен быть мастером 
  SPI1->CR1 &= ~SPI_CR1_DFF;               //8 bit data
  SPI1->CR1 &= ~SPI_CR1_CPOL;             //Polarity cls signal CPOL = 0;
  SPI1->CR1 &= ~SPI_CR1_CPHA;             //Phase cls signal    CPHA = 0;
  SPI1->CR1    |= SPI_CR1_SSI;        //обеспечить высокий уровень программного NSS
  SPI1->CR1    |= SPI_CR1_SSM;        //разрешить программное формирование NSS
  SPI1->CR1 |= SPI_CR1_BR; // fpclk/256
  SPI1->CR1 &= ~SPI_CR1_LSBFIRST;
  
  SPI1->CR1    |= SPI_CR1_SPE;        //разрешить работу модуля SPI1
  
}
 
 
void dmaSend8(uint8_t data, uint32_t n) {
  
    DMA1_Channel3->CPAR |= (uint32_t)&(SPI1->DR); //В SPI1...
    DMA1_Channel3->CCR |= DMA_CCR3_PL; //Приоритет - очень высокий 
 
    DMA1_Channel3->CMAR = (uint32_t) data; 
    DMA1_Channel3->CNDTR     = n;
 
    DMA1_Channel3->CCR &= ~DMA_CCR3_CIRC; //Запрещаем работу DMA в циклическом режиме
    DMA1_Channel3->CCR |= DMA_CCR3_MINC;// Инкрементация памяти после каждой передачи включена
    DMA1_Channel3->CCR |= DMA_CCR3_DIR; //направление передачи из памяти в периферию
    DMA1_Channel3->CCR &= ~DMA_CCR3_PSIZE;//Размерность данных периферии 8 бит
    DMA1_Channel3->CCR &= ~DMA_CCR3_MSIZE;//Размерность данных памяти 8 бит
 
    DMA1_Channel3->CCR |= DMA_CCR3_EN; //Разрешаем работу 3-го канала DMA
}
 
 
  
 
void main () { 
  
 RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN;
 
 ALLpins_init ();
 SPI_inint ();
 Tx_DMA_Ch3 ();
 
 
 dmaSend8(0x08, 1);
  
 __enable_irq();
  
  
  while(1);
  
}
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
14.12.2018, 17:56
Vozz, а в какой момент вы смотрите на то что получили?, точнее где точку останова ставите?
0
1 / 1 / 0
Регистрация: 22.06.2016
Сообщений: 96
14.12.2018, 18:02  [ТС]
Останов не ставлю после того как отладчик проходит dmaSend8(0x08, 1); в SPI1->DR появляется число, только неправильное
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
14.12.2018, 18:12
Vozz, как то это не правильно) У вас SPI работает на частоте 93 кГц чтобы вытолкнуть 8 бит ему нужно 8 тактов. А процессор молотит на частоте 24 МГц и после установки EN выходит из функции, то есть у вас физически не успеет байт убежать и в DR может быть что угодно. Попробуйте после функции полить флаг RXNE SPI и когда он будет 1 посмотреть что в DR ну или точку останова поставить на прерывание DMA
0
1 / 1 / 0
Регистрация: 22.06.2016
Сообщений: 96
15.12.2018, 16:12  [ТС]
В общем кое-что получилось. Теперь в SPI1->DR лежит то, что отправил! Но без указателей или массивов тут не обойтись, просто передать переменную не удается. Теперь нужно подтягивать теорию по указателям.
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
15.12.2018, 16:20
Vozz, ну а как вы хотели? DMA это аппаратный инструмент работы с памятью напрямую, указатели - сотовый инструмент. Я же вам сразу написал про массив) ибо локальная переменная живёт только пока выполняется функция, а потом на её физическом адресе может быть что угодно)
0
1 / 1 / 0
Регистрация: 22.06.2016
Сообщений: 96
16.12.2018, 18:21  [ТС]
Бой был непростым, но DMA+SPI наконец-то повержен. Оказывается, у ILI9341 реакция не особо и ему после переключения режимов CS/DC нужно вносить задержки, иначе чем выше скорость - тем больше байтов потеряется по пути к TFT. Выжал максимум при SPI1_BR = /2 обновляется экран быстро, но все же... хотелось бы побыстрее.
Надеюсь, мой пример кому-нибудь поможет

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
#include "stm32f10x.h"
#include "commands.h"
 
 
#define RED         0xf800
#define GREEN       0x07e0
#define BLUE        0x001f
#define BLACK       0x0000
#define YELLOW      0xffe0
#define WHITE       0xffff
#define CYAN        0x07ff
#define BRIGHT_RED  0xf810
#define GRAY1       0x8410
#define GRAY2       0x4208
 
#define TFT_CS_LOW      GPIOC->BSRR = GPIO_BSRR_BR0;
#define TFT_CS_HIGH     GPIOC->BSRR = GPIO_BSRR_BS0;
#define TFT_DC_LOW      GPIOC->BSRR = GPIO_BSRR_BR1;
#define TFT_DC_HIGH     GPIOC->BSRR = GPIO_BSRR_BS1;
#define TFT_RST_LOW     GPIOA->BSRR = GPIO_BSRR_BR2;
#define TFT_RST_HIGH            GPIOA->BSRR = GPIO_BSRR_BS2;
 
#define dmaWaitBSY() while(SPI1->SR & SPI_SR_BSY);
#define dmaWaitTXE() while(!(SPI1->SR & SPI_SR_TXE));
#define spi8() {SPI1->CR1 &= ~SPI_CR1_SPE; SPI1->CR1 &= ~SPI_CR1_DFF; SPI1->CR1 |= SPI_CR1_SPE;}
#define spi16() {SPI1->CR1 &= ~SPI_CR1_SPE; SPI1->CR1 |= SPI_CR1_DFF; SPI1->CR1 |= SPI_CR1_SPE;}
 
 
void DMA1_Channel3_IRQHandler() {
  
    if (DMA1->ISR & DMA_ISR_TCIF3) {
        dmaWaitTXE();
        //dmaWaitBSY();
        DMA1_Channel3->CCR &= ~DMA_CCR3_EN; //Запрещаем работу 3-го канала DMA
        DMA1->IFCR |= DMA_IFCR_CTCIF3;
        //GPIOC->BSRR = GPIO_BSRR_BS8;
        TFT_CS_HIGH;
    }
}
 
void ALLpins_init () { 
  
  //PC0 - CS(3),PC1-DC(5), PA2 - RST(4),PA3 - LED, PA5 _SCK(7),PA6 - MISO(9),PA7 - MOSI(6)
  
GPIOC->CRL &= ~GPIO_CRL_CNF0;    GPIOC->CRL &= ~GPIO_CRL_CNF1;
GPIOC->CRL |= GPIO_CRL_MODE0;    GPIOC->CRL |= GPIO_CRL_MODE1;
 
GPIOC->CRH &= ~GPIO_CRH_CNF8;    GPIOC->CRH &= ~GPIO_CRH_CNF9;
GPIOC->CRH |= GPIO_CRH_MODE8;    GPIOC->CRH |= GPIO_CRH_MODE9;
   
GPIOA->CRL &= ~GPIO_CRL_CNF2;    GPIOA->CRL &= ~GPIO_CRL_CNF3;
GPIOA->CRL |= GPIO_CRL_MODE2;    GPIOA->CRL |= GPIO_CRL_MODE3;
 
 
   
     //вывод SCK: выход двухтактный, альтернативная функция, 50MHz
GPIOA->CRL   |=  GPIO_CRL_MODE5; GPIOA->CRL   &= ~GPIO_CRL_CNF5; GPIOA->CRL   |=  GPIO_CRL_CNF5_1;   
 
//вывод MISO: вход цифровой с подтягивающим резистором, подтяжка к плюсу
GPIOA->CRL   &= ~GPIO_CRL_MODE6; GPIOA->CRL   &= ~GPIO_CRL_CNF6; GPIOA->CRL   |=  GPIO_CRL_CNF6_1; GPIOA->BSRR   =  GPIO_BSRR_BS6;     
 
//вывод MOSI: выход двухтактный, альтернативная функция, 50MHz
GPIOA->CRL   |=  GPIO_CRL_MODE7; GPIOA->CRL   &= ~GPIO_CRL_CNF7; GPIOA->CRL   |=  GPIO_CRL_CNF7_1;   
 
}
 
 
void spi1_init () { 
  
  SPI1->CR1 &= ~SPI_CR1_BIDIMODE;
  SPI1->CR1 &= ~SPI_CR1_BIDIOE;
  SPI1->CR1    |= SPI_CR1_MSTR;       //контроллер должен быть мастером 
  SPI1->CR1 &= ~SPI_CR1_DFF;               //8 bit data
  SPI1->CR1 &= ~SPI_CR1_CPOL;             //Polarity cls signal CPOL = 0;
  SPI1->CR1 &= ~SPI_CR1_CPHA;             //Phase cls signal    CPHA = 0;
  SPI1->CR1    |= SPI_CR1_SSI;        //обеспечить высокий уровень программного NSS
  SPI1->CR1    |= SPI_CR1_SSM;        //разрешить программное формирование NSS
  SPI1->CR1 &= ~SPI_CR1_BR; // fpclk/2
  //SPI1->CR1 |= SPI_CR1_BR_0; // fpclk/4
  //SPI1->CR1 |= SPI_CR1_BR_1; // fpclk/8
  //SPI1->CR1 |= SPI_CR1_BR_0 | SPI_CR1_BR_1; // fpclk/16
  //SPI1->CR1 |= SPI_CR1_BR_2; // fpclk/32
  //SPI1->CR1 |= SPI_CR1_BR_0 | SPI_CR1_BR_2; // fpclk/64
  //SPI1->CR1 |= SPI_CR1_BR_1 | SPI_CR1_BR_2; // fpclk/128
 // SPI1->CR1 |= SPI_CR1_BR; // fpclk/256
  SPI1->CR1 &= ~SPI_CR1_LSBFIRST;
  SPI1->CR2 |= SPI_CR2_TXDMAEN;
  SPI1->CR1    |= SPI_CR1_SPE;        //разрешить работу модуля SPI1
  
}
 
 
void dmaSend8(uint8_t * data) { 
  
  DMA1_Channel3->CCR &= ~DMA_CCR3_EN; //Запрещаем работу 3-го канала DMA
  DMA1_Channel3->CPAR |= (uint32_t)(&(SPI1->DR)); //В SPI1...
  DMA1_Channel3->CCR |= DMA_CCR3_PL; //Приоритет - очень высокий 
  DMA1_Channel3->CMAR = (uint32_t)data; //Задаем адрес памяти - базовый адрес массива во флэше
  DMA1_Channel3->CNDTR = 1; //Количество пересылаемых значений
  DMA1_Channel3->CCR &= ~DMA_CCR3_CIRC; //Запрещаем работу DMA в циклическом режиме
  DMA1_Channel3->CCR |= DMA_CCR3_MINC;// Инкрементация памяти после каждой передачи включена
  DMA1_Channel3->CCR |= DMA_CCR3_DIR; //направление передачи из памяти в периферию
  DMA1_Channel3->CCR &= ~DMA_CCR3_PSIZE;//Размерность данных периферии 8 бит
  DMA1_Channel3->CCR &= ~DMA_CCR3_MSIZE;//Размерность данных памяти 8 бит
 
  DMA1_Channel3->CCR |= DMA_CCR3_EN; //Разрешаем работу 3-го канала DMA
 
 
}
 
 
void dmaSend16(uint16_t * data) { 
  
  DMA1_Channel3->CCR &= ~DMA_CCR3_EN; //Запрещаем работу 3-го канала DMA
  DMA1_Channel3->CPAR |= (uint32_t)(&(SPI1->DR)); //В SPI1...
  DMA1_Channel3->CCR |= DMA_CCR3_PL; //Приоритет - очень высокий 
  DMA1_Channel3->CMAR = (uint32_t)data; //Задаем адрес памяти - базовый адрес массива во флэше
  DMA1_Channel3->CNDTR = 1; //Количество пересылаемых значений
  DMA1_Channel3->CCR &= ~DMA_CCR3_CIRC; //Запрещаем работу DMA в циклическом режиме
  DMA1_Channel3->CCR |= DMA_CCR3_MINC;// Инкрементация памяти после каждой передачи включена
  DMA1_Channel3->CCR |= DMA_CCR3_DIR; //направление передачи из памяти в периферию
  DMA1_Channel3->CCR |= DMA_CCR3_PSIZE_0;//Размерность данных периферии 16 бит
  DMA1_Channel3->CCR |= DMA_CCR3_MSIZE_0;//Размерность данных памяти 16 бит
 
  DMA1_Channel3->CCR |= DMA_CCR3_EN; //Разрешаем работу 3-го канала DMA
  
}
 
void dmaSendCmd(uint8_t cmd) {
 
    TFT_CS_LOW;
    for(int i=0; i<1; i++);
    TFT_DC_LOW;
    for(int i=0; i<1; i++);
    spi8 ();
 
    dmaWaitTXE();
    dmaSend8(&cmd);   
 
}
 
 
void dmaSendData8(u8 data8) {
 
    TFT_CS_LOW;
    for(int i=0; i<1; i++);
    TFT_DC_HIGH;
    for(int i=0; i<1; i++);
    spi8 ();
    dmaSend8(&data8);
}
 
void dmaSendData16(u16  data16) {
  
    TFT_CS_LOW;
    for(int i=0; i<1; i++);
    TFT_DC_HIGH;
    for(int i=0; i<1; i++);
    spi16 ();
 
    dmaSend16(&data16);
 
}
 
void TFT_led(uint8_t state)
{
    if (state)
        GPIOA->BSRR = GPIO_BSRR_BS3;
    else
        GPIOA->BSRR = GPIO_BSRR_BR3;
}
 
 
 
void TFT_setCol(uint16_t StartCol, uint16_t EndCol)
{
    dmaSendCmd(0x2A);                                                      // Column Command address
    dmaSendData16(StartCol);
    dmaSendData16(EndCol);
}
 
void TFT_setPage(uint16_t StartPage, uint16_t EndPage)
{
    dmaSendCmd(0x2B);                                                      // Column Command address
    dmaSendData16(StartPage);
    dmaSendData16(EndPage);
}
 
void TFT_setXY(uint16_t poX, uint16_t poY)
{
    TFT_setCol(poX, poX);
    TFT_setPage(poY, poY);
    dmaSendCmd(0x2c);
}
 
void TFT_setPixel(uint16_t poX, uint16_t poY, uint16_t color)
{
    TFT_setXY(poX, poY);
    dmaSendData16(color);
}
 
 
void TFT_DrawVerticalLine (uint16_t PosX, uint16_t PosY, uint16_t height, uint16_t thickness, uint16_t colour)  {
  
    uint16_t i=0,j=0;
  
    if (thickness>0) {
  
  for (i=PosY; i<height+PosY; i++) {
    for (j=PosX;j<thickness+PosX;j++) {
      
    TFT_setPixel(i,j, colour);
    
 
  } 
    }
      }
        }
 
 
void tft_init () { 
 
  TFT_RST_LOW;
  for(int i=0; i<1000; i++);
  TFT_RST_HIGH;
  for(int i=0; i<5000; i++);
   
  //Начинаем слать команды и данные в TFT !!!
  dmaSendCmd(LCD_POWERA);        dmaSendData8(0x39); dmaSendData8(0x2C); dmaSendData8(0x00); dmaSendData8(0x34); dmaSendData8(0x02);
  dmaSendCmd(LCD_POWERB);        dmaSendData8(0x00); dmaSendData8(0xC1); dmaSendData8(0x30);
  dmaSendCmd(LCD_DTCA);          dmaSendData8(0x85); dmaSendData8(0x00); dmaSendData8(0x78);
  dmaSendCmd(LCD_DTCB);          dmaSendData8(0x00); dmaSendData8(0x00);
  dmaSendCmd(LCD_POWER_SEQ);     dmaSendData8(0x64); dmaSendData8(0x03); dmaSendData8(0x12); dmaSendData8(0x81);
  dmaSendCmd(LCD_PRC);           dmaSendData8(0x20);
  dmaSendCmd(LCD_POWER1);        dmaSendData8(0x23);
  dmaSendCmd(LCD_POWER2);        dmaSendData8(0x10);
  dmaSendCmd(LCD_VCOM1);         dmaSendData8(0x3E); dmaSendData8(0x28);
  dmaSendCmd(LCD_VCOM2);         dmaSendData8(0x86);
  dmaSendCmd(LCD_MAC);           dmaSendData8(0x48);
  dmaSendCmd(LCD_PIXEL_FORMAT);  dmaSendData8(0x55);
  dmaSendCmd(LCD_FRMCTR1);       dmaSendData8(0x00); dmaSendData8(0x18);
  dmaSendCmd(LCD_DFC);           dmaSendData8(0x08); dmaSendData8(0x82); dmaSendData8(0x27);
  dmaSendCmd(LCD_3GAMMA_EN);     dmaSendData8(0x00);
  dmaSendCmd(LCD_GAMMA);         dmaSendData8(0x01);
  
  dmaSendCmd(LCD_PGAMMA);        dmaSendData8(0x0F); dmaSendData8(0x31); dmaSendData8(0x2B); dmaSendData8(0x0C); dmaSendData8(0x0E); dmaSendData8(0x08);
                                 dmaSendData8(0x4E); dmaSendData8(0xF1); dmaSendData8(0x37); dmaSendData8(0x07); dmaSendData8(0x10); dmaSendData8(0x03);
                                 dmaSendData8(0x0E); dmaSendData8(0x09); dmaSendData8(0x00);
                           
  dmaSendCmd(LCD_NGAMMA);        dmaSendData8(0x00); dmaSendData8(0x0E); dmaSendData8(0x14); dmaSendData8(0x03); dmaSendData8(0x11); dmaSendData8(0x07);
                                 dmaSendData8(0x31); dmaSendData8(0xC1); dmaSendData8(0x48); dmaSendData8(0x08); dmaSendData8(0x0F); dmaSendData8(0x0C);
                                 dmaSendData8(0x31); dmaSendData8(0x36); dmaSendData8(0x0F);
  dmaSendCmd(LCD_SLEEP_OUT); 
  
  for(int u=0; u<1000; u++); //Задержка 
  dmaSendCmd(LCD_DISPLAY_ON); 
  dmaSendCmd(LCD_GRAM);
  
  
  
  }
    
 
 
void main () { 
  
 RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_SPI1EN;//Тактируем порты A,B,C, регистр альтернативных функций выводов, АЦП, SPI1 и TIM1
 RCC->AHBENR |= RCC_AHBENR_DMA1EN; //Тактируем DMA1
 
 ALLpins_init ();
 spi1_init ();
 
  DMA1_Channel3->CCR |= DMA_CCR3_TCIE;
  NVIC_EnableIRQ(DMA1_Channel3_IRQn);
 
 tft_init ();
  
 TFT_led(1);
 
 for (int i=0; i<500000;i++);
  
 TFT_DrawVerticalLine (40, 40, 100, 5, BLACK);
  
 
  while(1);
  
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
16.12.2018, 18:21

Вывод информации из бд через ссылку
Добрый день. Сразу хочу отметить что мой вопрос может показаться лёгким для некоторой части людей. Однако хочу заметить что используя PDO...

Вывод информации из БД через форму
Всем привет. Я новичок в php и прошу у вас помощи. Необходимо сделать следующий скрипт php -&gt; Пользователь вводит в форму...

Вывод информации из БД через форму
Всем привет. Я новичок в php и прошу у вас помощи. Необходимо сделать следующий скрипт php -&gt; Пользователь вводит в форму...

Вывод информации через MS Word
Здраствуйте! Подскажите плз как вывести информацию из БД через MS Word. Заранее большое спасибо!

Вывод информации через скрипт
Возникла у меня тут пара вопросов относительно вывода информации через скрипт. Первое - я никак не могу понять как обратится к объекту не...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
56
Ответ Создать тему
Новые блоги и статьи
Ноутбук Альфария
kumehtar 24.08.2026
Встретился тут в сети ноутбук Альфария, примарха Альфа-Легиона. Хотя возможно, это ноутбук Омегона, разумеется. Ну как вам?
Мастера простых решений
DevAlt 23.08.2026
В сишарп стэках winforms, да и wpf существует сложная система связывания источниках данных и элементов формы(текстовые поля и метки), опирается все это на технологию событий и мета. . .
Цена ошибки
DevAlt 23.08.2026
Человек я беспокойный и потому заинтересовался OCaml, в чате форсили функторы модулей как суперфичу. Пытаясь отдуплить концепт, наткнулся на тутор с простым примером. А главный принцип обучения от. . .
Сегодня суббота, 22.08.2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины.
zorxor 22.08.2026
Сегодня суббота, 22. 08. 2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины. Кто Я, откуда Я пришел и куда Я иду? Эти вопросы не оставляют меня ни на секунду. Жизнь на планете Земля. . .
Жизня: рисунок укладки багажа, сделанный клодом
anaschu 21.08.2026
Сделал 15 снимков, он по снимкам сделал схему.
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru