SN_Tool_LedDisplay(1).c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. #include "SN_Tool_LedDisplay.h"
  2. /*
  3. 文件名:SN_Tool_LedDisplay.c/.h
  4. 作者: SN_FAE_黄泽洪
  5. 免责声明:无版权,可随意传播和篡改,该代码仅供开发参考,如需使用请自行验证
  6. 本人不担负商业使用上带来的风险。
  7. */
  8. /*
  9. 演示方式:
  10. int main(void)
  11. {
  12. SN_SYSCLK_set(SYSCLK_48MHZ);//配置系统时钟
  13. std_delay_init();// Systick初始化
  14. std_delayms(3000); //必须延时,例程使用了PA2仿真口,除非引出复位引脚
  15. SN_Tool_LedDisplay_Init(); //初始化数码管引脚设置
  16. SN_TIM1_CALL_set(200 ,TIM1_AGAIN_WORK ,SN_LED_Dis_point,NVIC_PRIO_0); //设置一个定时函数,定时刷新数码管,SN_LED_Dis_point()是数码管打点函数,每次中断打一个亮点
  17. while(1)
  18. {
  19. SN_DisPlay_Number(123);
  20. std_delayms(500);
  21. SN_DisPlay_Number(4567);
  22. std_delayms(500);
  23. SN_DisPlay_Clear();
  24. std_delayms(500);
  25. SN_DisPlay_Number(6284);
  26. std_delayms(500);
  27. }
  28. }
  29. */
  30. /*
  31. 4位数码管,共阴型号 ELF-5461AW 。
  32. ----------------------硬件引脚分配---------------------------
  33. 位选 PB0 - PB3 状态只有推挽置高 推挽置低
  34. 4 : PB0
  35. 3 : PB1
  36. 2 : PB2
  37. 1 : PB3
  38. 段码 PA0 - PA7 状态只有推挽置高 推挽置高
  39. a : PA0
  40. b : PA1
  41. c : PA2
  42. d : PA3
  43. e : PA4
  44. f : PA5
  45. g : PA6
  46. dp : PA7
  47. 注意:该演示代码直接使用寄存器,不适合移植和修改IO引脚,仅供演示!!
  48. 段码亮的状态 位选为推挽置低 段码为推挽置高
  49. 段码暗的状态 位选为推挽置高 段码为推挽置高
  50. */
  51. //4位数码管,字符编码表(共阴):
  52. uint8_t SN_CODE_G_DisPlay[10] = {
  53. 0X3F,//"0"
  54. 0X06,//"1"
  55. 0X5B,//"2"
  56. 0X4F,//"3"
  57. 0X66,//"4"
  58. 0X6D,//"5"
  59. 0X7D,//"6"
  60. 0X07,//"7"
  61. 0X7F,//"8"
  62. 0X6F,//"9"
  63. };
  64. //打点数据
  65. __IO uint8_t SN_CODE_G_Point[4]={0};
  66. //当前使用的COM位
  67. __IO uint8_t SN_G_COM = 0XFF;
  68. /*
  69. 函数名:SN_Tool_LedDisplay_Init
  70. 功能:初始数码管使用的IO
  71. 参数:无
  72. 返回值:无
  73. */
  74. void SN_Tool_LedDisplay_Init(void){
  75. /*设置数码管引脚*/
  76. //设置位选 PB0-PB3
  77. std_gpio_init_t gpio_config = {0};
  78. /* 使能位选对应的GPIO时钟 */
  79. std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOB);
  80. /* 配置IO */
  81. gpio_config.pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
  82. gpio_config.mode = GPIO_MODE_OUTPUT;
  83. gpio_config.pull = GPIO_PULLUP;
  84. gpio_config.output_type = GPIO_OUTPUT_PUSHPULL;
  85. /* 初始化GPIOB */
  86. std_gpio_init(GPIOB, &gpio_config);
  87. //设置段码 PA0-PA7
  88. /* 使能段码对应的GPIO时钟 */
  89. std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA);
  90. /* 配置IO */
  91. gpio_config.pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 \
  92. |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
  93. gpio_config.mode = GPIO_MODE_OUTPUT;
  94. gpio_config.pull = GPIO_PULLDOWN ;
  95. gpio_config.output_type = GPIO_OUTPUT_PUSHPULL;
  96. /* 初始化GPIOA */
  97. std_gpio_init(GPIOA, &gpio_config);
  98. //禁止输出
  99. std_gpio_set_pin(GPIOB, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
  100. std_gpio_reset_pin(GPIOA,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
  101. }
  102. /*
  103. 函数名:SN_LED_Dis_point
  104. 功能:用于点亮单独的LED灯
  105. 参数:无
  106. 返回值:无
  107. 点对应的段码LED,动态扫描的打点函数,定时器中断调用。
  108. 每次中断处理一个点,直到32个点完全打完
  109. 本文件不实现定时中断,直接调用SN_TIM1_INIT.C的接口
  110. */
  111. void SN_LED_Dis_point(void){
  112. static uint8_t pt = 25;
  113. uint32_t temp = 0;
  114. //"pt归零"
  115. if(pt > 31 ) { pt = 0; return ;}
  116. //关闭seg,修改COM前必须要提前关闭seg,否则有残影
  117. GPIOA->ODR = 0X00; //对应bit设置成推挽置1 关闭所有的seg
  118. //选择COM口,被选中的COM推挽置低,其他的设置成模拟输入模式
  119. GPIOB->ODR |= 0X0000000F; //全部置成1
  120. temp = 1U << (pt >> 3) ; //选择bit位
  121. GPIOB->ODR &= (~temp); //设置对应比特位 = 0
  122. //设置seg
  123. temp = 0;
  124. //根据缓冲区的数据,设置推挽置高
  125. if( ( SN_CODE_G_Point[(pt >> 3)] >> (pt % 8)) & 0x01 ){
  126. temp = 1U << (pt % 8) ; //设置置高的seg位
  127. GPIOA->ODR = temp;
  128. }
  129. //"pt自增"
  130. pt++;
  131. }
  132. /*
  133. 函数名:SN_DisPlay_Clear
  134. 功能:清除显示内容
  135. 参数:无
  136. 返回值:无
  137. */
  138. void SN_DisPlay_Clear(void){
  139. //填充编码到打点区,过程禁止中断响应
  140. __disable_irq ();
  141. SN_CODE_G_Point[0]= 0;
  142. SN_CODE_G_Point[1]= 0;
  143. SN_CODE_G_Point[2]= 0;
  144. SN_CODE_G_Point[3]= 0;
  145. __enable_irq();
  146. }
  147. /*
  148. 函数名:SN_DisPlay_Number
  149. 功能:显示数字内容
  150. 参数:0-9999
  151. 返回值:无
  152. 注意:添加小数点就在对应的com数据后面 SN_CODE_G_Point[x]|= 0X80
  153. 由此点亮dp位
  154. */
  155. void SN_DisPlay_Number(uint16_t num){
  156. //拆分个十百千
  157. uint8_t GW = 0; //个位
  158. uint8_t SW = 0; //十位
  159. uint8_t BW = 0; //百位
  160. uint8_t QW = 0; //千位
  161. QW = (uint8_t) (num / 1000); //千位
  162. BW = (uint8_t) ((num / 100) % 10); //百位
  163. SW = (uint8_t) ((num / 10) % 10); //十位
  164. GW = (uint8_t) (num % 10); //个位
  165. //填充编码到打点区,过程禁止中断响应
  166. __disable_irq ();
  167. SN_CODE_G_Point[0]= SN_CODE_G_DisPlay[GW] ; //个位
  168. if(num>9) {SN_CODE_G_Point[1]= SN_CODE_G_DisPlay[SW] ;}else{SN_CODE_G_Point[1]= 0;} //十位
  169. if(num>99){SN_CODE_G_Point[2]= SN_CODE_G_DisPlay[BW] ;}else{SN_CODE_G_Point[2]= 0;} //百位
  170. if(num>999 ){SN_CODE_G_Point[3]= SN_CODE_G_DisPlay[QW] ;}else{SN_CODE_G_Point[3]= 0;} //千位
  171. __enable_irq();
  172. }