• 丐版电子沙漏


     只是想简单地用8*8LED点阵实现一下类电子沙漏。没有陀螺仪,没有改变方向自动找平的功能,只实现最简单的下落堆积的功能。对,就是个伪电子沙漏,那么开始吧...

    主控:CH32V307

    8*8点阵驱动:2个595

     一、源码

    1. /********************************** (C) COPYRIGHT *******************************
    2. * File Name : main.c
    3. * Author : WCH
    4. * Version : V1.0.0
    5. * Date : 2021/06/06
    6. * Description : Main program body.
    7. *********************************************************************************
    8. * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
    9. * Attention: This software (modified or not) and binary are used for
    10. * microcontroller manufactured by Nanjing Qinheng Microelectronics.
    11. *******************************************************************************/
    12. #include "debug.h"
    13. /*在中断里面调用的变量需要使用 volatile 修饰*/
    14. volatile uint8_t gpio_interrupt_flag=0;
    15. /* Global typedef */
    16. /* 595 这里只定义了1个595的3个pin,应该有第2个595,实现从上面的沙漏到下一沙漏,我暂时只用了1个595,每次只显示上面或下面一个沙漏*/
    17. #define LED_SER GPIO_Pin_13
    18. #define LED_RCK GPIO_Pin_14
    19. #define LED_SRCK GPIO_Pin_15
    20. #define LED_SER_SET GPIO_WriteBit(GPIOB, LED_SER,Bit_SET)
    21. #define LED_SER_CLR GPIO_WriteBit(GPIOB, LED_SER,Bit_RESET)
    22. #define LED_SRCK_SET GPIO_WriteBit(GPIOB, LED_SRCK,Bit_SET)
    23. #define LED_SRCK_CLR GPIO_WriteBit(GPIOB, LED_SRCK,Bit_RESET)
    24. #define LED_RCK_SET GPIO_WriteBit(GPIOB, LED_RCK,Bit_SET)
    25. #define LED_RCK_CLR GPIO_WriteBit(GPIOB, LED_RCK,Bit_RESET)
    26. /* Global define */
    27. //用两个数组分布代表上下2个沙漏的数据,低电平点亮
    28. //可以理解为显存,每个显存8个字节,8*8=64bit,对应8*8LED的64个点
    29. u8 matrix1[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    30. u8 matrix2[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
    31. //由于LED的COM和SEG都是595控制,需要定义COM的控制数据,用于点亮一行,高电平有效
    32. //0x01代表第一个行,以此类推
    33. const u8 pos[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
    34. /* Global Variable */
    35. /*
    36. * @prief GPIO初始化
    37. */
    38. void LED_GPIO_Init(void)
    39. {
    40. GPIO_InitTypeDef GPIO_InitStructure = {0};
    41. NVIC_InitTypeDef NVIC_InitStructure = {0};
    42. EXTI_InitTypeDef EXTI_InitStructure = {0};
    43. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    44. GPIO_InitStructure.GPIO_Pin = LED_SER|LED_RCK|LED_SRCK;
    45. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    46. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    47. GPIO_Init(GPIOB, &GPIO_InitStructure);
    48. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO |RCC_APB2Periph_GPIOA, ENABLE);
    49. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    50. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    51. GPIO_Init(GPIOA, &GPIO_InitStructure);
    52. /*设置PA2作为中断线的GPIO引脚*/
    53. GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource2);
    54. /*设置GPIO中断*/
    55. EXTI_InitStructure.EXTI_Line = EXTI_Line0;//中断线0
    56. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式
    57. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
    58. EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能
    59. EXTI_Init(&EXTI_InitStructure);
    60. /*配置中断优先等级*/
    61. NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//外部中断0
    62. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占式优先级
    63. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//响应式优先级
    64. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能
    65. NVIC_Init(&NVIC_InitStructure);
    66. }
    67. /**
    68. * @brief 中断函数
    69. * 按键中断和沙漏无关
    70. **/
    71. __attribute__((interrupt("WCH-Interrupt-fast"))) //中断函数前加这上这句,告诉编译器这个是中断函数
    72. void EXTI0_IRQHandler(void)
    73. {
    74. if(EXTI_GetITStatus(EXTI_Line0)!=RESET)//产生中断
    75. {
    76. gpio_interrupt_flag=1;
    77. EXTI_ClearITPendingBit(EXTI_Line0);//清除中断标志
    78. }
    79. }
    80. /*
    81. * @prief 控制595串行输入
    82. * PN:反显
    83. * */
    84. void HC595(u8 c,u8 PN)
    85. {
    86. u8 i;
    87. for(i=0;i<8;i++){
    88. if(PN==0){ //正常显示
    89. if((c>>i) & 0x01) LED_SER_SET;
    90. else LED_SER_CLR;
    91. }
    92. else{ //反显
    93. if((c>>i) & 0x01) LED_SER_CLR;
    94. else LED_SER_SET;
    95. }
    96. LED_SRCK_CLR;
    97. LED_SRCK_SET; // 上升沿进行一次数据移入
    98. }
    99. }
    100. /*
    101. * @prief 显示pBuff指向的8个字节数据的内容到8*8led
    102. *
    103. */
    104. void Matrix8x8(u8 *pBuff)
    105. {
    106. unsigned char k;
    107. unsigned int m,n;
    108. for(m=0;m<32;m++) //为移动预留
    109. {
    110. for(n=0;n<32;n++)//控制显示速度,防止闪烁
    111. {
    112. for(k=0;k<8;k++) //行扫描
    113. {
    114. HC595(~pos[k],0);
    115. HC595(~pBuff[k],0);
    116. Delay_Us(10);
    117. LED_RCK_CLR;
    118. LED_RCK_SET; //并行输出
    119. }
    120. }
    121. }
    122. }
    123. /*
    124. * @prief 上沙漏最下一个点不断闪烁
    125. */
    126. void sandflash(u8 bright)
    127. {
    128. u8 oldVal=matrix1[7];
    129. if(bright==1){
    130. matrix1[7]=(0x7F&oldVal)|0x80;
    131. Matrix8x8(matrix1);
    132. }else{
    133. matrix1[7]=0x7F&oldVal;
    134. Matrix8x8(matrix1);
    135. }
    136. matrix1[7]=oldVal; //
    137. }
    138. /*
    139. * @prief 初始化沙漏
    140. * @param matrix:8字节显存;val:初始的内容
    141. */
    142. void resetHourglass(u8 *matrix,u8 val)
    143. {
    144. u8 i;
    145. for(i=0;i<8;i++){
    146. matrix[i]=val;
    147. }
    148. }
    149. /*
    150. * @prief 上沙漏演示
    151. */
    152. void hourglass1()
    153. {
    154. u8 i,j;
    155. for(j=0;j<15;j++){ //上沙漏,需要循环14次,将沙子漏完
    156. if(j<8){ //上8个和后面处理不同
    157. for(i=0;i<=j/2;i++){ //分成2部分
    158. sandflash(1);
    159. matrix1[i] =(matrix1[i] << 1) | 0x01; //左半部分处理,就是左移,或上第1位
    160. Matrix8x8(matrix1);
    161. sandflash(0);
    162. if(i!=j%8-i){ //如果前面没处理,那么执行
    163. sandflash(1);
    164. matrix1[j%8-i] =(matrix1[j%8-i] << 1) | 0x01; //右半部分,也是就是左移,或上第1位
    165. Matrix8x8(matrix1);
    166. sandflash(0);
    167. }
    168. }
    169. }
    170. else{
    171. for(i=0;i<((7-j%8)-1)/2+1;i++){ //上沙漏,下半部分处理,也是分左右两半
    172. sandflash(1);
    173. matrix1[i+j%8+1] =(matrix1[i+j%8+1] << 1) | 0x01; //左移,或上第1位
    174. Matrix8x8(matrix1);
    175. sandflash(0);
    176. if(i+j%8+1!=j-(i+j%8+1)){
    177. sandflash(1);
    178. matrix1[j-(i+j%8+1)] =(matrix1[j-(i+j%8+1)] << 1) | 0x01; //左移,或上第1位
    179. Matrix8x8(matrix1);
    180. sandflash(0);
    181. }
    182. }
    183. }
    184. }
    185. }
    186. /*
    187. * @prief 下沙漏一个沙子向下落
    188. */
    189. void sandflow(u8 step)
    190. {
    191. u8 i;
    192. for(i=0;i//step是下落步数
    193. matrix2[i]=matrix2[i]&~(0x01<//显示
    194. Matrix8x8(matrix2);
    195. matrix2[i]=matrix2[i]|(0x01<//消隐
    196. Matrix8x8(matrix2);
    197. }
    198. }
    199. /*
    200. * @prief 下沙漏演示
    201. * 点亮低电平有效
    202. */
    203. void hourglass2(void)
    204. {
    205. u8 i,j;
    206. for(i=0;i<8;i++){
    207. for(j=0;j
    208. {
    209. sandflow(8-i);
    210. matrix2[7-j]=matrix2[7-j]&~(0x80>>i); //每一行都要设置一个(0x80>>i)
    211. Matrix8x8(matrix2);
    212. sandflow(8-i);
    213. matrix2[7-i]=matrix2[7-i]&~(0x80>>j); //第7-i行要设置(0x80>>j)
    214. Matrix8x8(matrix2);
    215. }
    216. sandflow(8-i);
    217. matrix2[7-i]=matrix2[7-i]&~(0x80>>i); //第7-i行也要设置一个(0x80>>i)
    218. Matrix8x8(matrix2);
    219. }
    220. }
    221. /*********************************************************************
    222. * @fn main
    223. *
    224. * @brief Main program.
    225. *
    226. * @return none
    227. */
    228. int main(void)
    229. {
    230. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    231. SystemCoreClockUpdate();
    232. Delay_Init();
    233. USART_Printf_Init(115200);
    234. printf("SystemClk:%d\r\n",SystemCoreClock);
    235. printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );
    236. printf("This is printf example\r\n");
    237. LED_GPIO_Init();
    238. while(1)
    239. {
    240. /*按键中断,预留,和沙漏演示无关*/
    241. if (gpio_interrupt_flag==1) {//有中断产生
    242. gpio_interrupt_flag=0;
    243. }
    244. //上沙漏演示
    245. hourglass1();
    246. //初始化上沙漏显存
    247. resetHourglass(matrix1,0x00);
    248. //下沙漏演示
    249. hourglass2();
    250. //初始化下沙漏显存
    251. resetHourglass(matrix2,0xFF);
    252. }
    253. }

    二、演示

  • 相关阅读:
    漏洞复现--中远麒麟堡垒机SQL注入
    [java/初学者/GUI编程]GUI界面设计——界面组件类
    计算机网络知识点整理(待更新)
    WebService SOAP1.1 SOAP1.12 HTTP PSOT方式调用
    百度秋招突击手册面试算法题:三数之和
    基于Java+Swing+Socket实现中国象棋-网络版
    Spring依赖注入源码解析(上)
    SynthText流程解读 - 不看代码不知道的那些事
    【flask入门系列】Cookie与Session
    window系统下为django自动绘制模型类关系图
  • 原文地址:https://blog.csdn.net/weixin_44067125/article/details/134517743