Browse Source

Display work.

Vladimir N. Shilov 3 years ago
parent
commit
2cde0f39bd
5 changed files with 155 additions and 125 deletions
  1. 1 1
      Makefile
  2. 20 0
      ReadMe.txt
  3. 4 0
      inc/board.h
  4. 1 33
      inc/font8x8_basic.h
  5. 129 91
      src/board.c

+ 1 - 1
Makefile

@@ -75,7 +75,7 @@ INCLUDES += -I$(PERIPHLIBPATH)/CMSIS/Device/ST/STM32F0xx/Include
 ifeq ($(DEBUG), 1)
 OPT = -O0 -ggdb
 else
-OPT = -Os
+OPT = -O2
 endif
 OPT += -ffunction-sections -fdata-sections
 OPT += -fomit-frame-pointer -falign-functions=16

+ 20 - 0
ReadMe.txt

@@ -27,3 +27,23 @@ Display Ctrl	HT1632C (устаревшая, не лучший выбор)
 Самый большой косяк - прогадал с индикатором, визуально нужно поднять примерно 
 на 5 мм. Нижий ряд точек (или два) ниже края стекла.
 По плате удалось поднять на 3.5 мм - и нужно перезаказывать.
+---
+2022.09.05
+
+Домучал изврат...
+Управление индикатором:
+ - ногодрыг для управления: команды 12 бит, задание адреса 10 бит, MSB
+ - данные заливаются по DMA SPI, 8 бит, LSB
+без задержек, на максимальной скорости, работает вопреки даташиту.
+
+Яркость слабая, нужно менять резисторные сборки на меньшие.
+
+Нужно подбирать шрифт, "стандартные" шрифты отображаються "лёжа" - 
+повёрнутые на 90 градусов по часовой стрелке.
+Плюс нужны украинские буквы.
+
+Похоже, я неправильно сделал схему - нужно было наоборот групировать 
+индикаторы, ряды а не колонки, по момей схеме. И новые платы уже едут...
+И неуверен или это получится на этих индикаторах, или нужны с другой 
+"полярностью".
+Предвижу незабываемый "секас" с реализацией бегущей строки...

+ 4 - 0
inc/board.h

@@ -13,7 +13,11 @@
 /* Variables */
 /* Exported funcions */
 void Board_Init(void);
+void HT1632C_Write_bits(uint16_t data, uint16_t nbits);
+void HT1632C_Write_Cmd(uint16_t data, uint16_t nbits);
+void HT1632C_Write_Data(const uint8_t * data, uint8_t addr, uint8_t len);
 void EXTI4_15_IRQHandler(void);
+void DMA1_Channel2_3_IRQHandler(void);
 void display_test(void);
 
 #endif /* _BOARD_H_ */

+ 1 - 33
inc/font8x8_basic.h

@@ -20,39 +20,7 @@
 
 // Constant: font8x8_basic
 // Contains an 8x8 font map for unicode points U+0000 - U+007F (basic latin)
-char font8x8_basic[128][8] = {
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0000 (nul)
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0001
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0002
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0003
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0004
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0005
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0006
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0007
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0008
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0009
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+000A
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+000B
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+000C
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+000D
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+000E
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+000F
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0010
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0011
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0012
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0013
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0014
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0015
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0016
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0017
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0018
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0019
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+001A
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+001B
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+001C
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+001D
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+001E
-    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+001F
+char font8x8_basic[96][8] = {
     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0020 (space)
     { 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00},   // U+0021 (!)
     { 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},   // U+0022 (")

+ 129 - 91
src/board.c

@@ -1,11 +1,15 @@
 #include "main.h"
 
 /* private defines */
-#define SPI_BUFFER_SIZE   (uint16_t)(24*8)
+#define SPI_BUFFER_SIZE   (uint16_t)(24)
 
 /* private macros */
 #define HT1632C_CS_ON     GPIOA->BRR = (1<<15)
 #define HT1632C_CS_OFF    GPIOA->BSRR = (1<<15)
+#define HT1632C_WR_LOW    GPIOB->BRR = (1<<3)
+#define HT1632C_WR_HGH    GPIOB->BSRR = (1<<3)
+#define HT1632C_DATA_0    GPIOB->BRR = (1<<5)
+#define HT1632C_DATA_1    GPIOB->BSRR = (1<<5)
 
 /* private variables */
 static uint8_t display_Buffer[SPI_BUFFER_SIZE] = {0};
@@ -43,6 +47,9 @@ void Board_Init(void)
   NVIC_EnableIRQ(RCC_IRQn);
 
   /* Initialize all configured peripherals */
+  HT1632C_CS_OFF;
+  HT1632C_WR_HGH;
+  HT1632C_DATA_1;
   GPIO_Init();
 
   /* DMA interrupt init */
@@ -54,17 +61,11 @@ void Board_Init(void)
 
   SPI1_Init();
   /** Star SPI transfer to shift registers */
-  /* Set DMA source and destination addresses. */
-  /* Source: Address of the SPI buffer. */
-  DMA1_Channel3->CMAR = (uint32_t)&display_Buffer;
-  /* Destination: SPI1 data register. */
+  /* DMA Destination addr: SPI1 data register. */
   DMA1_Channel3->CPAR = (uint32_t)&(SPI1->DR);
-  /* Set DMA data transfer length (SPI buffer length). */
-  DMA1_Channel3->CNDTR = SPI_BUFFER_SIZE;
   /* Enable SPI transfer */
-  //SPI1->CR1 |= SPI_CR1_SPE;
+  SPI1->CR1 |= SPI_CR1_SPE;
 //  Flag.SPI_TX_End = 1;
-  //GPIOA->BRR = (1<<15); // set ~CS low
 
 //  TIM1_Init();
 //  TIM3_Init();
@@ -77,77 +78,37 @@ void Board_Init(void)
 /* output 'L', 'G', '5' */
 void display_test(void) {
   // prepare buffer
-  display_Buffer[1] = 0xfe;
-  display_Buffer[2] = 0x02;
-  display_Buffer[3] = 0x02;
-  display_Buffer[4] = 0x02;
-  display_Buffer[5] = 0x02;
-
-  display_Buffer[9] = 0x7c;
-  display_Buffer[10] = 0x82;
-  display_Buffer[11] = 0x92;
-  display_Buffer[12] = 0x92;
-  display_Buffer[13] = 0x5e;
-
-  display_Buffer[16] = 0xf4;
-  display_Buffer[17] = 0x92;
-  display_Buffer[18] = 0x92;
-  display_Buffer[19] = 0x92;
-  display_Buffer[20] = 0x8c;
-
-  // init ht1632
-  // disable spi
-  SPI1->CR1 &= ~(SPI_CR1_SPE);
-  // disable dma tranfer & clear data width bits
-  SPI1->CR2 &= ~(SPI_CR2_TXDMAEN | SPI_CR2_DS);
-  // set data width to 12 bit for command mode
-  SPI1->CR2 |= (SPI_CR2_DS_3 | SPI_CR2_DS_1 | SPI_CR2_DS_0);
-  // enable spi
-  SPI1->CR1 |= SPI_CR1_SPE;
-  // select chip
-  HT1632C_CS_ON;
-  // wite for spi
-  while ((SPI1->SR & SPI_SR_BSY) != 0);
-  // transfer command
-  SPI1->DR = 0x802; // 100 0000 0001 0 -- SYS_EN
-  // wite for spi
-  while ((SPI1->SR & SPI_SR_TXE) == 0);
-  SPI1->DR = 0x806; // 100 0000 0011 0 -- LED_ON
-  // wite for spi
-  while ((SPI1->SR & SPI_SR_BSY) != 0);
-  // deselect chip
-  HT1632C_CS_OFF;
-  // disable spi
-  SPI1->CR1 &= ~(SPI_CR1_SPE);
+  display_Buffer[0] = 0x7f;
+  display_Buffer[1] = 0x46;
+  display_Buffer[2] = 0x16;
+  display_Buffer[3] = 0x1e;
+  display_Buffer[4] = 0x16;
+  display_Buffer[5] = 0x06;
+  display_Buffer[6] = 0x0f;
+  display_Buffer[7] = 0x00;
 
-  // set 10 bit data width for write cmd
-  SPI1->CR2 &= ~(SPI_CR2_DS);
-  SPI1->CR2 |= (SPI_CR2_DS_3 | SPI_CR2_DS_0);
-  // enable spi
-  SPI1->CR1 |= SPI_CR1_SPE;
-  // select chip
-  HT1632C_CS_ON;
-  // wite for spi
-  while ((SPI1->SR & SPI_SR_BSY) != 0);
-  // transfer command
-  SPI1->DR = 0x280; // 101 0000000 -- write from addr 0x0
-  // wite for spi
-  while ((SPI1->SR & SPI_SR_BSY) != 0);
-  // deselect chip
-  HT1632C_CS_OFF;
-  // disable spi
-  SPI1->CR1 &= ~(SPI_CR1_SPE);
+  display_Buffer[8] = 0x3c;
+  display_Buffer[9] = 0x66;
+  display_Buffer[10] = 0x03;
+  display_Buffer[11] = 0x03;
+  display_Buffer[12] = 0x33;
+  display_Buffer[13] = 0x66;
+  display_Buffer[14] = 0x7c;
+  display_Buffer[15] = 0x00;
 
-  // set 8 bit data width for data
-  SPI1->CR2 &= ~(SPI_CR2_DS);
-  SPI1->CR2 |= (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0);
-  // enable spi
-  SPI1->CR1 |= SPI_CR1_SPE;
-  // select chip
-  HT1632C_CS_ON;
-  // start transfer
-  SPI1->CR2 |= (SPI_CR2_TXDMAEN);
-  DMA1_Channel3->CCR |= DMA_CCR_EN;
+  display_Buffer[16] = 0x3f;
+  display_Buffer[17] = 0x03;
+  display_Buffer[18] = 0x1f;
+  display_Buffer[19] = 0x30;
+  display_Buffer[20] = 0x30;
+  display_Buffer[21] = 0x33;
+  display_Buffer[22] = 0x1e;
+  display_Buffer[23] = 0x00;
+
+  HT1632C_Write_Cmd(0x802, 0x800);
+  HT1632C_Write_Cmd(0x806, 0x800);
+
+  HT1632C_Write_Data(display_Buffer, 0x0, SPI_BUFFER_SIZE);
 }
 
 /**
@@ -171,7 +132,7 @@ static void GPIO_Init(void)
    PA8  - Buzzer (AF2 for TIM1_CH1)
    PA15 - ~CS / SPI_NSS (AF0)
    PB4  - ~RD / SPI_MISO (AF0) - NOT USED
-   * Select output mode (10) AF+OD+PU, High Speed
+   * Select output mode (10) AF+OD, High Speed
    PB3  - ~WR / SPI_SCK (AF0)
    PB5  - Data / SPI_MOSI (AF0)
    PB6  - SCL (AF1)
@@ -180,20 +141,17 @@ static void GPIO_Init(void)
   // MODE Output
   GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER8 | GPIO_MODER_MODER15)) \
                 | (GPIO_MODER_MODER8_0 | GPIO_MODER_MODER15_0);
-  GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER3|GPIO_MODER_MODER5|GPIO_MODER_MODER6|GPIO_MODER_MODER7)) \
-                | (GPIO_MODER_MODER3_1|GPIO_MODER_MODER5_1|GPIO_MODER_MODER6_1|GPIO_MODER_MODER7_1);
+  GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODER3|GPIO_MODER_MODER5)) \
+                | (GPIO_MODER_MODER3_0|GPIO_MODER_MODER5_0);
   // Pull-Up
   GPIOA->PUPDR = (GPIOA->PUPDR & ~(GPIO_PUPDR_PUPDR8 | GPIO_PUPDR_PUPDR15)) \
                 | (GPIO_PUPDR_PUPDR8_0 | GPIO_PUPDR_PUPDR15_0);
-  /*GPIOB->PUPDR = (GPIOB->PUPDR & ~(GPIO_PUPDR_PUPDR3|GPIO_PUPDR_PUPDR5|GPIO_PUPDR_PUPDR6|GPIO_PUPDR_PUPDR7)) \
-                | (GPIO_PUPDR_PUPDR3_0|GPIO_PUPDR_PUPDR5_0|GPIO_PUPDR_PUPDR6_0|GPIO_PUPDR_PUPDR7_0);*/
   // High Speed
   GPIOA->OSPEEDR = (GPIO_OSPEEDR_OSPEEDR8|GPIO_OSPEEDR_OSPEEDR15);
   GPIOB->OSPEEDR = (GPIO_OSPEEDR_OSPEEDR3|GPIO_OSPEEDR_OSPEEDR5 \
                   |GPIO_OSPEEDR_OSPEEDR6|GPIO_OSPEEDR_OSPEEDR7);
   // Open Drain
-  GPIOB->OTYPER = (GPIO_OTYPER_OT_3|GPIO_OTYPER_OT_5 \
-                  |GPIO_OTYPER_OT_6|GPIO_OTYPER_OT_7);
+  GPIOB->OTYPER = (GPIO_OTYPER_OT_6|GPIO_OTYPER_OT_7);
   // AF1 for PB6 & PB7
   GPIOB->AFR[0] = (0x1<<24) | (0x1<<28);
 
@@ -241,17 +199,81 @@ static void SPI1_Init(void)
 {
   /* SPI1 DMA Init */
   /* SPI1_TX Init: Priority high, Memory increment, read from memory, non-circular mode,
-     ?Enable DMA transfer complete/error interrupts */
-  DMA1_Channel3->CCR = (DMA_CCR_PL_1 | DMA_CCR_MINC | DMA_CCR_DIR); // DMA_CCR_CIRC | DMA_CCR_TEIE | DMA_CCR_DIR | DMA_CCR_TCIE
+     Enable DMA transfer complete/error interrupts */
+  DMA1_Channel3->CCR = (DMA_CCR_PL_1 | DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_CIRC | DMA_CCR_TCIE); // | DMA_CCR_TEIE
 
   /* SPI1 interrupt Init */
   NVIC_SetPriority(SPI1_IRQn, 0);
   NVIC_EnableIRQ(SPI1_IRQn);
 
-  /* SPI1 parameter configuration: master mode, data 8 bit, divider = 64, TX DMA */
-  // SPI_CR1_CPOL ?
-  SPI1->CR1 = (SPI_CR1_MSTR | SPI_CR1_BR_2 | SPI_CR1_BR_0 | SPI_CR1_SSM | SPI_CR1_SSI); // SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE | 
-  SPI1->CR2 = (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0 | SPI_CR2_TXDMAEN); // | SPI_CR2_FRXTH);
+  /* SPI1 parameter configuration: master mode, data 8 bit, divider = 2, TX DMA */
+  SPI1->CR1 = (SPI_CR1_MSTR | SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_CPOL | SPI_CR1_CPHA | SPI_CR1_LSBFIRST);
+  SPI1->CR2 = (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0 | SPI_CR2_TXDMAEN);
+}
+
+/**
+ * @brief Write <nbits> bit of data to selected HT1632Cs
+ * @param data words to write, nbits of bits (1<<(num-1))
+ */
+void HT1632C_Write_bits(const uint16_t data, uint16_t nbits) {
+  do {
+    HT1632C_WR_LOW;
+
+    if (data & nbits) {
+      HT1632C_DATA_1;
+    } else {
+      HT1632C_DATA_0;
+    }
+//    _delay_half_us();
+    HT1632C_WR_HGH;
+//    _delay_half_us();
+  } while (nbits >>= 1);
+}
+
+/**
+ * @brief Write CMD to selected HT1632Cs
+ * @param data words to write
+ * @param nbits cmd len in bits (1<<(num-1))
+ */
+void HT1632C_Write_Cmd(const uint16_t data, uint16_t nbits) {
+  // GPIO pin mode
+  GPIOB->MODER &= ~(GPIO_MODER_MODER3 | GPIO_MODER_MODER5);
+  GPIOB->MODER |= (GPIO_MODER_MODER3_0 | GPIO_MODER_MODER5_0);
+
+  HT1632C_CS_ON;
+  HT1632C_Write_bits(data, nbits);
+  HT1632C_CS_OFF;
+}
+
+/**
+ * @brief Write Data to selected HT1632Cs
+ * @param data pointer to data array
+ * @param addr begin address
+ * @param len bytes to write
+ */
+void HT1632C_Write_Data(const uint8_t * data, const uint8_t addr, const uint8_t len) {
+  uint16_t a = 0x280 | (addr & 0x7f);
+
+  /* DMA Source addr: Address of the SPI buffer. */
+  DMA1_Channel3->CMAR = (uint32_t)&data[0];
+  /* Set DMA data transfer length (SPI buffer length). */
+  DMA1_Channel3->CNDTR = len;
+
+  // GPIO pin mode
+  GPIOB->MODER &= ~(GPIO_MODER_MODER3 | GPIO_MODER_MODER5);
+  GPIOB->MODER |= (GPIO_MODER_MODER3_0 | GPIO_MODER_MODER5_0);
+
+  HT1632C_CS_ON;
+  HT1632C_Write_bits(a, 0x200);
+
+  // SPI pin mode
+  GPIOB->MODER &= ~(GPIO_MODER_MODER3 | GPIO_MODER_MODER5);
+  GPIOB->MODER |= (GPIO_MODER_MODER3_1 | GPIO_MODER_MODER5_1);
+
+  // start transfer
+  SPI1->CR2 |= (SPI_CR2_TXDMAEN);
+  DMA1_Channel3->CCR |= DMA_CCR_EN;
+  // End of transaction in DMA1_Channel2_3_IRQHandler
 }
 
 /**
@@ -266,3 +288,19 @@ void EXTI4_15_IRQHandler(void)
     //ES_PlaceEvent(evNewSecond);
   }
 }
+
+/**
+  * @brief This function handles DMA1 channel 2 and 3 interrupts.
+  */
+void DMA1_Channel2_3_IRQHandler(void) {
+  if ((DMA1->ISR & DMA_ISR_TCIF3) != 0) {
+    // clear interrupt flag
+    DMA1->IFCR = DMA_IFCR_CTCIF3;
+    // disable transfer
+    DMA1_Channel3->CCR &= ~(DMA_CCR_EN);
+    // wite for spi
+    while ((SPI1->SR & SPI_SR_BSY) != 0) { __NOP(); };
+    // deselect chip
+    HT1632C_CS_OFF;
+  }
+}