main.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /*
  2. u8g2_dma_test, 2MHz uC Clock
  3. */
  4. #include <stdio.h>
  5. #include "stm32l031xx.h"
  6. #include "delay.h"
  7. #include "u8g2.h"
  8. /*=======================================================================*/
  9. /* external functions */
  10. uint8_t u8x8_gpio_and_delay_stm32l0_sw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
  11. uint8_t u8x8_gpio_and_delay_stm32l0_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
  12. uint8_t u8x8_byte_stm32l0_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
  13. uint8_t u8x8_byte_stm32l0_dma_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
  14. /*=======================================================================*/
  15. /* global variables */
  16. u8g2_t u8g2; // u8g2 object
  17. uint8_t u8g2_x, u8g2_y; // current position on the screen
  18. volatile unsigned long SysTickCount = 0;
  19. void __attribute__ ((interrupt, used)) SysTick_Handler(void)
  20. {
  21. SysTickCount++;
  22. }
  23. void setHSIClock()
  24. {
  25. /* test if the current clock source is something else than HSI */
  26. if ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
  27. {
  28. /* enable HSI */
  29. RCC->CR |= RCC_CR_HSION;
  30. /* wait until HSI becomes ready */
  31. while ( (RCC->CR & RCC_CR_HSIRDY) == 0 )
  32. ;
  33. /* enable the HSI "divide by 4" bit */
  34. RCC->CR |= (uint32_t)(RCC_CR_HSIDIVEN);
  35. /* wait until the "divide by 4" flag is enabled */
  36. while((RCC->CR & RCC_CR_HSIDIVF) == 0)
  37. ;
  38. /* then use the HSI clock */
  39. RCC->CFGR = (RCC->CFGR & (uint32_t) (~RCC_CFGR_SW)) | RCC_CFGR_SW_HSI;
  40. /* wait until HSI clock is used */
  41. while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
  42. ;
  43. }
  44. /* disable PLL */
  45. RCC->CR &= (uint32_t)(~RCC_CR_PLLON);
  46. /* wait until PLL is inactive */
  47. while((RCC->CR & RCC_CR_PLLRDY) != 0)
  48. ;
  49. /* set latency to 1 wait state */
  50. FLASH->ACR |= FLASH_ACR_LATENCY;
  51. /* At this point the HSI runs with 4 MHz */
  52. /* Multiply by 16 device by 2 --> 32 MHz */
  53. RCC->CFGR = (RCC->CFGR & (~(RCC_CFGR_PLLMUL| RCC_CFGR_PLLDIV ))) | (RCC_CFGR_PLLMUL16 | RCC_CFGR_PLLDIV2);
  54. /* enable PLL */
  55. RCC->CR |= RCC_CR_PLLON;
  56. /* wait until the PLL is ready */
  57. while ((RCC->CR & RCC_CR_PLLRDY) == 0)
  58. ;
  59. /* use the PLL has clock source */
  60. RCC->CFGR |= (uint32_t) (RCC_CFGR_SW_PLL);
  61. /* wait until the PLL source is active */
  62. while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
  63. ;
  64. SystemCoreClockUpdate(); /* Update SystemCoreClock global variable */
  65. }
  66. /*
  67. Enable several power regions: PWR, GPIOA
  68. This must be executed after each reset.
  69. */
  70. void startUp(void)
  71. {
  72. RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
  73. RCC->IOPENR |= RCC_IOPENR_IOPBEN; /* Enable clock for GPIO Port B */
  74. RCC->APB1ENR |= RCC_APB1ENR_PWREN; /* enable power interface (PWR) */
  75. PWR->CR |= PWR_CR_DBP; /* activate write access to RCC->CSR and RTC */
  76. SysTick->LOAD = (SystemCoreClock/1000)*10 - 1; /* 10ms task */
  77. SysTick->VAL = 0;
  78. SysTick->CTRL = 7; /* enable, generate interrupt (SysTick_Handler), do not divide by 2 */
  79. }
  80. /*=======================================================================*/
  81. /* u8x8 display procedures */
  82. /*
  83. SPI clock ~500KHz ?
  84. uc1609_slg19264_f 2Mhz SW SPI 0.3 FPS BSS 1692
  85. uc1609_slg19264_f 2Mhz HW SPI 4.7 FPS BSS 1692
  86. uc1609_slg19264_f 2Mhz DMA SPI 5.0 FPS BSS 1948
  87. uc1609_slg19264_1 2Mhz SW SPI 0.3 FPS BSS 348
  88. uc1609_slg19264_1 2Mhz HW SPI 2.6 FPS BSS 348
  89. uc1609_slg19264_1 2Mhz DMA SPI 2.6 FPS BSS 604
  90. SPI clock ~6MHz ?
  91. uc1609_slg19264_f 32Mhz SW SPI 6.0 FPS BSS 1692
  92. uc1609_slg19264_f 32Mhz HW SPI 73.8 FPS BSS 1692
  93. uc1609_slg19264_f 32Mhz DMA SPI 76.7 FPS BSS 1948 .
  94. uc1609_slg19264_1 32Mhz SW SPI 5.6 FPS BSS 348
  95. uc1609_slg19264_1 32Mhz HW SPI 39.6 FPS BSS 348
  96. uc1609_slg19264_1 32Mhz DMA SPI 40.7 FPS BSS 604
  97. */
  98. void initDisplay(void)
  99. {
  100. /* setup display */
  101. //u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R2, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_stm32l0_sw_i2c);
  102. //u8g2_Setup_uc1609_slg19264_f(&u8g2, U8G2_R2, u8x8_byte_4wire_sw_spi, u8x8_gpio_and_delay_stm32l0_spi);
  103. u8g2_Setup_uc1609_slg19264_f(&u8g2, U8G2_R2, u8x8_byte_stm32l0_hw_spi, u8x8_gpio_and_delay_stm32l0_spi);
  104. //u8g2_Setup_uc1609_slg19264_f(&u8g2, U8G2_R2, u8x8_byte_stm32l0_dma_spi, u8x8_gpio_and_delay_stm32l0_spi);
  105. u8g2_InitDisplay(&u8g2);
  106. u8g2_SetPowerSave(&u8g2, 0);
  107. }
  108. void outChar(uint8_t c)
  109. {
  110. u8g2_x+=u8g2_DrawGlyph(&u8g2, u8g2_x, u8g2_y, c);
  111. }
  112. void outStr(const char *s)
  113. {
  114. while( *s )
  115. outChar(*s++);
  116. }
  117. void outHexHalfByte(uint8_t b)
  118. {
  119. b &= 0x0f;
  120. if ( b < 10 )
  121. outChar(b+'0');
  122. else
  123. outChar(b+'a'-10);
  124. }
  125. void outHex8(uint8_t b)
  126. {
  127. outHexHalfByte(b >> 4);
  128. outHexHalfByte(b);
  129. }
  130. void outHex16(uint16_t v)
  131. {
  132. outHex8(v>>8);
  133. outHex8(v);
  134. }
  135. void outHex32(uint32_t v)
  136. {
  137. outHex16(v>>16);
  138. outHex16(v);
  139. }
  140. void setRow(uint8_t r)
  141. {
  142. u8g2_x = 0;
  143. u8g2_y = r;
  144. }
  145. /*=======================================================================*/
  146. int main()
  147. {
  148. uint8_t v = 0;
  149. uint32_t frame_cnt = 0;
  150. uint32_t start, diff, fps, fps_frac;
  151. //setHSIClock(); /* enable 32 MHz Clock */
  152. SystemCoreClockUpdate();
  153. startUp(); /* enable systick irq and several power regions */
  154. initDisplay(); /* aktivate display */
  155. GPIOA->MODER &= ~GPIO_MODER_MODE9; /* clear mode */
  156. GPIOA->MODER |= GPIO_MODER_MODE9_0; /* Output mode */
  157. GPIOA->OTYPER &= ~GPIO_OTYPER_OT_9; /* no open drain */
  158. GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED9; /* low speed */
  159. GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEED9_1; /* 10 MHz */
  160. GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD9; /* no pullup/pulldown */
  161. GPIOA->BSRR = GPIO_BSRR_BR_9; /* atomic clear */
  162. frame_cnt = 0;
  163. fps = 0;
  164. fps_frac = 0;
  165. start = SysTickCount;
  166. for(;;)
  167. {
  168. diff = SysTickCount - start;
  169. if ( diff > 0 )
  170. {
  171. fps = frame_cnt*1000 / diff; // diff are 10ms ticks
  172. fps_frac = fps % 10;
  173. fps /= 10;
  174. }
  175. GPIOA->BSRR = GPIO_BSRR_BR_9; /* atomic clear */
  176. //u8g2_SetContrast(&u8g2, v);
  177. //u8g2_ClearBuffer(&u8g2);
  178. u8g2_FirstPage(&u8g2);
  179. do
  180. {
  181. u8g2_SetFont(&u8g2, u8g2_font_6x12_tf);
  182. u8g2_DrawStr(&u8g2, 0,12, "STM32L031");
  183. u8g2_DrawStr(&u8g2, 0,24, u8x8_u8toa(SystemCoreClock/1000000, 2));
  184. u8g2_DrawStr(&u8g2, 20,24, "MHz");
  185. u8g2_SetFont(&u8g2, u8g2_font_9x15B_tf);
  186. u8g2_DrawStr(&u8g2, 0,40, u8x8_u8toa(v, 3));
  187. u8g2_DrawStr(&u8g2, 0,60, "FPS:");
  188. u8g2_DrawStr(&u8g2, 35,60, u8x8_u8toa( fps, 3));
  189. u8g2_DrawStr(&u8g2, 35+3*8,60, ".");
  190. u8g2_DrawStr(&u8g2, 35+3*8+6,60, u8x8_u8toa( fps_frac, 1));
  191. } while( u8g2_NextPage(&u8g2));
  192. GPIOA->BSRR = GPIO_BSRR_BS_9; /* atomic clear */
  193. //u8g2_SendBuffer(&u8g2);
  194. v++;
  195. frame_cnt++;
  196. }
  197. return 0;
  198. }