蓝桥杯嵌入式综合工程

最近在准备蓝桥杯,写了一个垃圾的小程序,算是比较综合的程序了,大家有什么好的想法我也可以试试,欢迎大家提问!!

最后有工程链接!!!

最后有工程链接!!!

最后有工程链接!!!

使用的是STM32G431RB单片机,hal库配置,把基本的配置都加进去了

主要外设:

LED,ADC,RTC,IIC,串口

主要功能都集中在按键和串口

1、按键可以识别单击、双击、长按、短按、并且获取键值,内部结构体还可以获取上一次键值,按键按下间隔时间,按键按下时间

2、串口使用不定长数据接收,暂时还没有做更多功能,不定长使用的是定时器中断查询方式,没有使用串口空闲中断,(就是太垃圾)但是用起来效果还可以。

开放工程大家一起学习,代码哪里有问题的欢迎指正。

贴一下主要代码:

#include "user_app.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"

uint8_t buffer[1];                //串口接收缓存
int frequency_tim2=0;            //定时器2频率
int frequency_tim3=0;            //定时器3频率
float zkb1=0.00;                    //定时器3占空比
float zkb2=0.00;                    //定时器4占空比

RTC_TimeTypeDef time;            //当前时间(在sys中断中调用)
RTC_DateTypeDef data;            //当前日期(在sys中断中调用)
uint16_t delay_time=0;        //计算按键按下时长
uint32_t delay_ms_sign=0;    //计算按键按下间隔时长

//按键结构体
typedef struct key
{
    uint16_t key_time;                                //按键按下时间
    uint8_t key_count;                                //按键计数
    uint16_t time_lag;                                //两次按键的时间间隔    
    uint8_t last_key_data;                        //记住上一次键值
    _Bool double_key;                                    //0表示单击,1表示双击
    _Bool long_press;                                    //0表示短按,1表示长按
    void (*get_data)(uint8_t *kdata);    //函数指针指向获取按键函数
}KEY;

static KEY key1;        //创建一个KEY类型数据

/*============================================
*
*        user_main    :    用户主函数
*
============================================*/
void user_main(void)
{
    char *pf;
    pf=malloc(20);                    //申请显示内存
    
    uint8_t key=15;                    //存储的按键值
    
    key1.key_time=0;                //初始按键按下时间
    key1.get_data=get_key;    //函数指针指向获取按键值的函数
    key1.time_lag=0;                //初始按键间隔时间
    key1.double_key=0;            //初始为单击
    key1.last_key_data=0;        //初始上一次按键值
    
    user_init();                        //用户初始化

    while(1)
    {
    
        sprintf(pf,"frequency1:%dHZ ",frequency_tim3);
        LCD_DisplayStringLine(Line3,(uint8_t *)pf);
        sprintf(pf,"frequency2:%dHZ ",frequency_tim2);
        LCD_DisplayStringLine(Line4,(uint8_t *)pf);

        sprintf(pf,"frequency1:%.2f ",zkb1);
        LCD_DisplayStringLine(Line5,(uint8_t *)pf);
        sprintf(pf,"frequency2:%.2f",zkb2);
        LCD_DisplayStringLine(Line6,(uint8_t *)pf);

        sprintf(pf,"time:%02d:%02d:%02d",time.Hours,time.Minutes,time.Seconds);
        LCD_DisplayStringLine(Line7,(uint8_t *)pf);
        
        sprintf(pf,"Starting up count:%d",read_at24c02(0));
        LCD_DisplayStringLine(Line8,(uint8_t *)pf);

        
        key1.get_data(&key);        //获取按键值
        
        
        if((key1.time_lag<500)&&(key1.last_key_data==key))//判断按键间隔时间是否小于500,而且与上一次键值相等
        {
            key1.double_key=1;//双击
        }
        else
        {
            key1.double_key=0;//单击
        }

        if(key1.key_time >350)//按键按下时间是否大于400
        {
            key1.long_press=1;//长按
        }
        else
        {
            key1.long_press=0;//短按
        }
        
        if(key!=15)
        {
            LCD_ClearLine(Line9);
            sprintf(pf,"K:%d long:%d double:%d",key,key1.long_press,key1.double_key);
            LCD_DisplayStringLine(Line9,(uint8_t *)pf);    
        }
        
        ADC_test(pf,&hadc1,Line1,5);
        ADC_test(pf,&hadc2,Line2,5);
    }
}

/*============================================
*
*        user_init    :    用户初始化函数
*
============================================*/
void user_init(void)
{
    char *pf;
    pf=malloc(20);
    RTC_TimeTypeDef set_time;    //定义当前时间
    
    set_time.Hours=17;                //设置小时
    set_time.Minutes=37;            //设置分钟
    set_time.Seconds=00;            //设置秒
    
    uint8_t start_up_count=0;    //存储开机次数
    
    I2CInit();                                //IIC初始化
    
    start_up_count=read_at24c02(0);                //读取开机次数
    write_at24c02(0,++start_up_count);        //写入开机次数
    
    HAL_UART_Receive_IT(&huart1,buffer,1);                            //打开串口接收中断
    HAL_RTC_SetTime(&hrtc,&set_time,RTC_FORMAT_BIN);        //设置当前时间
    
    HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);    //打开定时器输入中断
    HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);    //打开定时器输入中断
    HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);    //打开定时器输入中断
    HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);    //打开定时器输入中断
    
    LCD_Init();                //lcd初始化
    
    
    HAL_UART_Transmit(&huart1,(uint8_t *)"串口初始化完成!!!\r\n请输入数据\r\n",sizeof("串口初始化完成!!!\r\n请输入数据\r\n"),100);
    
    LCD_Clear(White);
    LCD_SetBackColor(White);
  LCD_SetTextColor(Red);
    LCD_DisplayStringLine(Line0,(uint8_t *)"   COMPREHENSIVE    ");
    
//    HAL_ADC_Start(&hadc1);//打开ADC1转换
//    HAL_ADC_Start(&hadc2);//打开ADC2转换
//    
//    ADC_test(pf,&hadc1,Line1 ,100);//ADC测试
//    ADC_test(pf,&hadc2,Line2 ,100);
    led_test(3,200);            //LED测试
}

/*============================================
*
*        led_test    :    led测试函数
*
*        num                :    闪烁次数,为奇数时最后关闭led;
*        delay_ms    :    延时时间(闪烁间隔时间)
*
============================================*/
void led_test(uint8_t num,uint16_t delay_ms)
{
    
    for(uint8_t i=0;i<num;i++)
    {
        HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_All);
        led_refresh();
        HAL_Delay(delay_ms);
    }
    
}

/*============================================
*
*        led_test    :    led刷新函数
*
============================================*/
void led_refresh(void)
{
    LED_START;
    LED_STOP;
}

/*============================================
*
*        ADC_test    :    ADC测试函数
*
*        pf                :    打印内存存储空间;
*        hadcx            :    延时时间
*        dsp_line    :    打印行数
*        delay_ms    :    打印延时
*
============================================*/
void ADC_test(char *pf,ADC_HandleTypeDef *hadcx,uint8_t dsp_line,uint16_t delay_ms)
{
    float adc_value=0;
    HAL_ADC_Start(hadcx);
    
    adc_value=HAL_ADC_GetValue(hadcx)*3;
    if(hadcx->Instance==ADC2)
    {
        sprintf(pf,"     ADC2:%.2f V ",adc_value/4095);
    }
    else
    {
        sprintf(pf,"     ADC1:%.2f V ",adc_value/4095);
    }
    
    LCD_DisplayStringLine(dsp_line,(uint8_t *)pf);

    HAL_Delay(delay_ms);    
}

/*============================================
*
*        HAL_UART_RxCpltCallback    :    串口回调函数
*
============================================*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    HAL_UART_Receive_IT(&huart1,buffer,1);//重新打开串口接受中断
}


/*============================================
*
*        HAL_TIM_IC_CaptureCallback    :    定时器输入回调函数
*
============================================*/
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    float tim2_ch1=0,tim2_ch2=0;//必须定义为float类型才能被运算
    float tim3_ch1=0,tim3_ch2=0;//必须定义为float类型才能被运算
    
    if(htim->Instance==TIM2)
    {    
        if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)//确定转换通道,不然两个通道都会进入获取
        {
            
            tim2_ch1=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//获取转换周期
            tim2_ch2=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2);//获取低电平时间

            __HAL_TIM_SetCounter(&htim2,0);//清楚定时器计数
            frequency_tim2=1000000/tim2_ch1;//计算频率
            zkb2=(float)(tim2_ch2/tim2_ch1)*100;//计算占空比

        }
    }
    
    if(htim->Instance==TIM3)
    {
        if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)
        {
            tim3_ch1=HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);
            tim3_ch2=HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2);
            frequency_tim3=1000000/tim3_ch1;
            zkb1=(tim3_ch2/tim3_ch1)*100;
            __HAL_TIM_SetCounter(&htim3,0);
        }
    }
    
    HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);//重新打开定时器输入转换
    HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);
    HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
    HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);    
}

/*============================================
*
*        read_at24c02    :    24c02读取函数
*
*        add                        :    读取地址;
*
============================================*/
uint8_t read_at24c02(uint8_t add)
{
    uint8_t data;
    I2CStart();
    I2CSendByte(0xa0);
    I2CWaitAck();
    
    I2CSendByte(add);
    I2CWaitAck();
    
    I2CStart();
    I2CSendByte(0xa1);
    I2CWaitAck();
    data=I2CReceiveByte();
    I2CSendNotAck();
    I2CStop();
    
    return data;

/*============================================
*
*        write_at24c02    :    24c02写入数据函数
*
*        add                        :    写入地址;
*        data                    :    写入数据
*
============================================*/
void write_at24c02(uint8_t add,uint8_t data)
{
    I2CStart();
    I2CSendByte(0xa0);
    I2CWaitAck();
    
    I2CSendByte(add);
    I2CWaitAck();
    
    I2CSendByte(data);
    I2CWaitAck();
    I2CStop();
    


///*============================================
//*
//*        write_at24c02    :    24c02写入数据函数
//*
//*        add                        :    写入地址;
//*        data                    :    写入数据
//*   我需要返回按键的次数
//*        按键的按下的时间
//*   按下的键值
//*
//============================================*/
//uint8_t get_key(void)
//{
//    uint8_t key_data=0;

//    if( (((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07))!=15 )
//    {
        if(delay_sign(5))
        {
//            if( (((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07))!=15 )
//            {
//                
                while((((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07))!=15)
                {
//                    
//                    switch((((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07)))
//                    {
//                        case 14    : key_data=1;break;
//                        case 13    : key_data=2;break;
//                        case 11    : key_data=3;break;
//                        case 07    : key_data=4;break;
//                        default : return key_data;
//                    }
                }
            }
//        }
//    }
//    return key_data;
//}


/*============================================
*
*        write_at24c02    :    24c02写入数据函数
*
*        add                        :    写入地址;
*        data                    :    写入数据
*   我需要返回按键的次数
*        按键的按下的时间
*   按下的键值
*
============================================*/
void get_key( uint8_t *key_data)
{
    static uint8_t keydata=0;//保存键值
    
    if( (((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07))!=15 )
    {
        HAL_Delay(5);
        if( (((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07))!=15 )
        {
            key1.last_key_data=keydata;//将保存的上一次键值付给结构体
            key1.time_lag= delay_ms_sign;
            delay_time=0;
            delay_ms_sign=0;
            while((((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07))!=15)
            {
                switch((((GPIOA->IDR&0x01)<<3)|(GPIOB->IDR&0x07)))
                {
                    case 14    : *key_data=1;    keydata=1;break;
                    case 13    : *key_data=2;    keydata=2;break;
                    case 11    : *key_data=3;    keydata=3;break;
                    case 07    : *key_data=4;    keydata=4;break;
                    default :  *key_data=*key_data;    break;
                }
            }
            key1.key_time=delay_time;
            key1.key_count++;
        }
    }
}


//_Bool delay_sign(uint16_t delay)
//{
//    delay_mark=1;
//    if(delay<delay_time)
//    {
//        delay_mark=0;
//        delay_time=0;
//        return 1;
//    }
//    else
//    {
//        return 0;
//    }
//}


//uint8_t dblclick(uint8_t key)
//{
//    
//    if(key == get_key())
//    {
//        
//    }
//}


//typedef struct keydata
//{
//    KEY KEYdata;
//    KEYdata.key
//    uint16_t key_time;
//    uint8_t key_count;
//}KEYDATA;

//void key_data_init()
//{

//}
 

收都收了,麻烦点个赞吧!!!

链接:https://pan.baidu.com/s/1cvUvt_tgbyGyj8Jci5_qxw?pwd=wcj7 
提取码:wcj7

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值