只是想简单地用8*8LED点阵实现一下类电子沙漏。没有陀螺仪,没有改变方向自动找平的功能,只实现最简单的下落堆积的功能。对,就是个伪电子沙漏,那么开始吧...
主控:CH32V307
8*8点阵驱动:2个595
一、源码
- /********************************** (C) COPYRIGHT *******************************
- * File Name : main.c
- * Author : WCH
- * Version : V1.0.0
- * Date : 2021/06/06
- * Description : Main program body.
- *********************************************************************************
- * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
- * Attention: This software (modified or not) and binary are used for
- * microcontroller manufactured by Nanjing Qinheng Microelectronics.
- *******************************************************************************/
-
-
- #include "debug.h"
-
-
- /*在中断里面调用的变量需要使用 volatile 修饰*/
- volatile uint8_t gpio_interrupt_flag=0;
-
- /* Global typedef */
- /* 595 这里只定义了1个595的3个pin,应该有第2个595,实现从上面的沙漏到下一沙漏,我暂时只用了1个595,每次只显示上面或下面一个沙漏*/
- #define LED_SER GPIO_Pin_13
- #define LED_RCK GPIO_Pin_14
- #define LED_SRCK GPIO_Pin_15
-
-
- #define LED_SER_SET GPIO_WriteBit(GPIOB, LED_SER,Bit_SET)
- #define LED_SER_CLR GPIO_WriteBit(GPIOB, LED_SER,Bit_RESET)
-
- #define LED_SRCK_SET GPIO_WriteBit(GPIOB, LED_SRCK,Bit_SET)
- #define LED_SRCK_CLR GPIO_WriteBit(GPIOB, LED_SRCK,Bit_RESET)
-
- #define LED_RCK_SET GPIO_WriteBit(GPIOB, LED_RCK,Bit_SET)
- #define LED_RCK_CLR GPIO_WriteBit(GPIOB, LED_RCK,Bit_RESET)
-
- /* Global define */
-
- //用两个数组分布代表上下2个沙漏的数据,低电平点亮
- //可以理解为显存,每个显存8个字节,8*8=64bit,对应8*8LED的64个点
- u8 matrix1[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
- u8 matrix2[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
-
-
- //由于LED的COM和SEG都是595控制,需要定义COM的控制数据,用于点亮一行,高电平有效
- //0x01代表第一个行,以此类推
- const u8 pos[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
-
-
- /* Global Variable */
- /*
- * @prief GPIO初始化
- */
- void LED_GPIO_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure = {0};
- NVIC_InitTypeDef NVIC_InitStructure = {0};
- EXTI_InitTypeDef EXTI_InitStructure = {0};
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
- GPIO_InitStructure.GPIO_Pin = LED_SER|LED_RCK|LED_SRCK;
-
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO |RCC_APB2Periph_GPIOA, ENABLE);
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
-
-
-
- /*设置PA2作为中断线的GPIO引脚*/
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource2);
-
- /*设置GPIO中断*/
- EXTI_InitStructure.EXTI_Line = EXTI_Line0;//中断线0
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能
- EXTI_Init(&EXTI_InitStructure);
-
- /*配置中断优先等级*/
- NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//外部中断0
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占式优先级
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;//响应式优先级
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能
- NVIC_Init(&NVIC_InitStructure);
- }
-
-
- /**
- * @brief 中断函数
- * 按键中断和沙漏无关
- **/
- __attribute__((interrupt("WCH-Interrupt-fast"))) //中断函数前加这上这句,告诉编译器这个是中断函数
- void EXTI0_IRQHandler(void)
- {
- if(EXTI_GetITStatus(EXTI_Line0)!=RESET)//产生中断
- {
- gpio_interrupt_flag=1;
- EXTI_ClearITPendingBit(EXTI_Line0);//清除中断标志
- }
- }
-
- /*
- * @prief 控制595串行输入
- * PN:反显
- * */
- void HC595(u8 c,u8 PN)
- {
- u8 i;
- for(i=0;i<8;i++){
-
- if(PN==0){ //正常显示
- if((c>>i) & 0x01) LED_SER_SET;
- else LED_SER_CLR;
- }
- else{ //反显
- if((c>>i) & 0x01) LED_SER_CLR;
- else LED_SER_SET;
- }
-
- LED_SRCK_CLR;
- LED_SRCK_SET; // 上升沿进行一次数据移入
- }
- }
-
- /*
- * @prief 显示pBuff指向的8个字节数据的内容到8*8led
- *
- */
- void Matrix8x8(u8 *pBuff)
- {
- unsigned char k;
- unsigned int m,n;
-
- for(m=0;m<32;m++) //为移动预留
- {
- for(n=0;n<32;n++)//控制显示速度,防止闪烁
- {
- for(k=0;k<8;k++) //行扫描
- {
- HC595(~pos[k],0);
- HC595(~pBuff[k],0);
- Delay_Us(10);
-
- LED_RCK_CLR;
- LED_RCK_SET; //并行输出
-
- }
-
- }
- }
- }
-
-
-
- /*
- * @prief 上沙漏最下一个点不断闪烁
- */
- void sandflash(u8 bright)
- {
- u8 oldVal=matrix1[7];
- if(bright==1){
- matrix1[7]=(0x7F&oldVal)|0x80;
- Matrix8x8(matrix1);
- }else{
- matrix1[7]=0x7F&oldVal;
- Matrix8x8(matrix1);
- }
- matrix1[7]=oldVal; //
- }
-
-
- /*
- * @prief 初始化沙漏
- * @param matrix:8字节显存;val:初始的内容
- */
- void resetHourglass(u8 *matrix,u8 val)
- {
- u8 i;
- for(i=0;i<8;i++){
- matrix[i]=val;
- }
- }
-
- /*
- * @prief 上沙漏演示
- */
- void hourglass1()
- {
- u8 i,j;
- for(j=0;j<15;j++){ //上沙漏,需要循环14次,将沙子漏完
- if(j<8){ //上8个和后面处理不同
-
- for(i=0;i<=j/2;i++){ //分成2部分
-
- sandflash(1);
- matrix1[i] =(matrix1[i] << 1) | 0x01; //左半部分处理,就是左移,或上第1位
- Matrix8x8(matrix1);
- sandflash(0);
-
- if(i!=j%8-i){ //如果前面没处理,那么执行
- sandflash(1);
- matrix1[j%8-i] =(matrix1[j%8-i] << 1) | 0x01; //右半部分,也是就是左移,或上第1位
- Matrix8x8(matrix1);
- sandflash(0);
- }
- }
-
- }
- else{
-
-
- for(i=0;i<((7-j%8)-1)/2+1;i++){ //上沙漏,下半部分处理,也是分左右两半
- sandflash(1);
- matrix1[i+j%8+1] =(matrix1[i+j%8+1] << 1) | 0x01; //左移,或上第1位
- Matrix8x8(matrix1);
- sandflash(0);
-
- if(i+j%8+1!=j-(i+j%8+1)){
- sandflash(1);
- matrix1[j-(i+j%8+1)] =(matrix1[j-(i+j%8+1)] << 1) | 0x01; //左移,或上第1位
- Matrix8x8(matrix1);
- sandflash(0);
- }
- }
- }
-
- }
-
- }
-
-
- /*
- * @prief 下沙漏一个沙子向下落
- */
- void sandflow(u8 step)
- {
- u8 i;
- for(i=0;i
//step是下落步数 - matrix2[i]=matrix2[i]&~(0x01<//显示
- Matrix8x8(matrix2);
- matrix2[i]=matrix2[i]|(0x01<//消隐
- Matrix8x8(matrix2);
- }
- }
-
- /*
- * @prief 下沙漏演示
- * 点亮低电平有效
- */
- void hourglass2(void)
- {
- u8 i,j;
-
- for(i=0;i<8;i++){
- for(j=0;j
- {
- sandflow(8-i);
- matrix2[7-j]=matrix2[7-j]&~(0x80>>i); //每一行都要设置一个(0x80>>i)
- Matrix8x8(matrix2);
- sandflow(8-i);
- matrix2[7-i]=matrix2[7-i]&~(0x80>>j); //第7-i行要设置(0x80>>j)
- Matrix8x8(matrix2);
- }
- sandflow(8-i);
- matrix2[7-i]=matrix2[7-i]&~(0x80>>i); //第7-i行也要设置一个(0x80>>i)
- Matrix8x8(matrix2);
- }
-
- }
-
-
-
- /*********************************************************************
- * @fn main
- *
- * @brief Main program.
- *
- * @return none
- */
- int main(void)
- {
-
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- SystemCoreClockUpdate();
- Delay_Init();
- USART_Printf_Init(115200);
- printf("SystemClk:%d\r\n",SystemCoreClock);
- printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );
- printf("This is printf example\r\n");
-
-
- LED_GPIO_Init();
-
- while(1)
- {
- /*按键中断,预留,和沙漏演示无关*/
- if (gpio_interrupt_flag==1) {//有中断产生
- gpio_interrupt_flag=0;
- }
-
- //上沙漏演示
- hourglass1();
- //初始化上沙漏显存
- resetHourglass(matrix1,0x00);
- //下沙漏演示
- hourglass2();
- //初始化下沙漏显存
- resetHourglass(matrix2,0xFF);
- }
- }
-
二、演示
