首页 > 其他分享 >蓝桥杯准备---练习日志

蓝桥杯准备---练习日志

时间:2024-01-21 15:33:07浏览次数:29  
标签:--- Rx 蓝桥 state Key printf GPIO 日志 data

2024-01-17

  利用Cubemx配置usart中Asyn... 和 Syn....的意思是什么?

 

使用串口时报错如下  ------解决办法:添加st官方提供的串口驱动文件

 修改底层printf内部的fputs代码  ---实现printf函数通过串口输出,需要利用LIB什么的......

我猜测这个函数是向某个文件流中写入一个字符,printf会调用这函数来向标准输出文件流写入字符(本来是),不过这里被改写为向usart发送了,所以..printf被重定向了。

int fputc(int c, FILE *stream)
{
  HAL_UART_Transmit(&huart1,(u8 *)&c,1,10);
  return c;
}

 

中断接收回调函数处理  ---每输入一个字符触发一次中断。如当串口助手中输入12345相当于进入了5次中断,这5次中断中Rx_Dat的值分别未‘1’‘2’‘3’‘4’‘5’,利用Rx_Data存储接下来的值

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance==USART1)
    {
        Rx_Data[Rx_Count] = Rx_Dat;
        Rx_Count++;
        
        HAL_UART_Transmit(&huart1,&Rx_Dat,1,1);    
        HAL_UART_Receive_IT(&huart1,&Rx_Dat,1);
    }
    if(Rx_Count == 10)
        HAL_UART_Transmit(&huart1,Rx_Data,10,1);


}

 

串口中断回调函数中重新接收不能太快执行不然会干扰原来的数据...........

 内存拷贝函数memcpy有方向性,别弄错了,而且串口接收到的数据最好放到一个静态变量中,防止后续变量输入干扰到

 

第12届蓝桥杯嵌入式习题练习

 

LED部分

 

由于部分引脚的和LCD重用,所以这里使用了锁存器,由LE来控制锁存器的使能,低电平有效。每次修改LED的控制需要调用一次下面的函数

      HAL_GPIO_WritePin(LED_CMD_GPIO_Port, LED_CMD_Pin, GPIO_PIN_SET);
      HAL_GPIO_WritePin(LED_CMD_GPIO_Port, LED_CMD_Pin, GPIO_PIN_RESET);

 

按键采集部分

uint8_t __BSP_Key_get()
{
    uint8_t temp = 0;
    
    if(HAL_GPIO_ReadPin(Button4_GPIO_Port,Button4_Pin) == 0 )
         temp = KEY4;
    if(HAL_GPIO_ReadPin(Button3_GPIO_Port,Button3_Pin) == 0 )
         temp = KEY3;
    if(HAL_GPIO_ReadPin(Button2_GPIO_Port,Button2_Pin) == 0 )
         temp = KEY2;
    if(HAL_GPIO_ReadPin(Button1_GPIO_Port,Button1_Pin) == 0 )
         temp = KEY1;
    return temp;

    
}

//采集按键值
uint8_t BSP_Key_get()
{
    uint8_t Key_num = 0;
    uint8_t Old_Key_num = 0;
    uint8_t Key_value = 0;
    Key_num = __BSP_Key_get();  //采集按下的按键值
    
  //防止按键抖动的操作 Key_value = Key_num & (Key_num ^ Old_Key_num); Old_Key_num = Key_num; return Key_value; }

LCD部分

官方提供了一个LCD显示库来显示

  LCD_Init();
  LCD_Clear(Black);  //清屏
  LCD_SetTextColor(White);  //设置字体颜色
  LCD_SetBackColor(Black);  //设置背景颜色    

sprintf(LCD_Content," CNBR:%d ",CNBR);
LCD_DisplayStringLine(Line4,LCD_Content);  //输出LCD_content中的内容

 

其它配置

 LCD_Disp ^=0x1;

  对LCD_Disp每次执行会在0,1之间循环数据变化

串口配置

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance==USART1)
    {        
        Rx_Data[Rx_Count++]=Rx_Dat;
    }    
    if(Rx_Count == 22)
    {
        Rx_flag = 1;
        printf("%s\r\n",Rx_Data);
        
    }
        //再次执行串口接收中断会干扰原来的数据,必须放在最末尾,数据最好另外保存
        HAL_UART_Receive_IT(&huart1,&Rx_Dat,1);   //执行该函数则输入一个字符就进一次中断
}

在需要的时候自写一个字符串比较和拷贝函数会比使用memcpy/strncpy来的方便

 uint8_t str_copy( void * source, void *destination,uint8_t n)
 {
    char *p1 = (char *)source;
    char *p2 = (char *)destination;
    uint8_t i =0;
    for( i =0;i<n;i++)
    {
        p2[i] = p1[i];
    }
    p2[i] = '\0';  //最后必须补充‘\0’
    return 0;

 
 }
//字符串比较
uint8_t str_cmp( void * str1, void *str2,uint8_t n)
{
    char *p1 = (char *)str1;
    char *p2 = (char *)str2;
    for(uint8_t i =0;i<n;i++)
    {
        if(p1[i] != p2[i])
            return 0xff;
    }
    return 0;


}

关于strncpy和memcpy

int main()
{
   char src[40];
   char dest[12];

   memset(dest, '\0', sizeof(dest));
   strcpy(src, "This is 2xkt.com");
   strncpy(dest, src, 10);

   printf("最终的目标字符串: %s\n", dest);

   return(0);
}

会从目标地址处复制n个字符到新地址中并自动补0.

相比较之下,memcpy则能应用于非字符的数组类型

 

 

串口的数据到来很适合利用状态机来处理分析数据的格式,内容等是否有错,条理狠清晰

void BSP_usart_proj()
{

    static uint8_t  data_state = 0;
    //接收到完整数据
    if(Rx_flag)
    {
        Rx_flag = 0;
        printf("数据输入正确\r\n");
        data_state = 1;
        
    #ifdef USART_DEBUG
        printf("当前state : %d\r\n",data_state);
        printf("串口收到数据:%s\r\n",Rx_Data);
    #endif
    }
    
    //检测数据格式
    else if(  data_state==1 )
    {
        if(usart_Type() == 1)
        {
            data_state = 2;    
            #ifdef USART_DEBUG
                printf("数据格式正确\r\n");
                printf("当前state : %d\r\n",data_state);
            #endif
             
        }
        else
        {
                printf("ERROR:数据格式出现问题");
                data_state = 0;
                Rx_Count = 0;
                    
        }
    }

    //检测数据内容
    else if( data_state == 2)
    {
        if(usart_content() == 1)
        {
            data_state = 3;    
            #ifdef USART_DEBUG
                printf("数据内容正确\r\n");
                printf("当前state : %d\r\n",data_state);
            #endif
        }
        else
        {
                    printf("ERROR:数据内容出现问题");
                    data_state = 0;
                    Rx_Count = 0;
        }
    }
    //检测完毕,开始输出
    else if( data_state == 3)
    {
        usart_data_proj();
            data_state = 0;    
            Rx_Count = 0;
    }
    
   
}

 

整体做下来的感觉

 1. DEBUG测试代码能写就写,不要嫌麻烦,不然后面找DEBUG有的是时间给你麻烦的...........

    #ifdef USART_DEBUG
    printf("数据内容正确\r\n");
    printf("当前state : %d\r\n",data_state);
    #endif        

 2. 写代码前最好将各模块都规划好再写,尤其是各模块之间的联系,其实就是FPGA中模块化的感觉。可以画图,做流程图将要做的事情分开规划好

 

  代码就不补充了,写的也一般。

 

标签:---,Rx,蓝桥,state,Key,printf,GPIO,日志,data
From: https://www.cnblogs.com/sujian4412/p/17971481

相关文章

  • 《the psychology of money》金钱心理学-英文原版书籍-读书笔记
    ————————————————————introduction————————————————————2024.01.20尽管我们周围的世界充满了明显的事物和现象,但人们往往忽视它们“softskills”financialsuccessisnotahardscience.Itisasoftskill,wherehowyoube......
  • 无涯教程-Node.js - 全局对象
    Node.js全局对象本质上是全局的,并且在所有模块中都可用,无涯教程不需要在应用程序中包含这些对象,而是可以直接使用它们。__filename__filename表示正在执行的代码的文件名,这是此代码文件的解析绝对路径,对于主程序,此文件名不必与命令行中使用的文件名相同,模块内部的值是该模......
  • 无涯教程-Node.js - Web模块
    Web服务器是一个软件应用程序,它处理HTTP客户端(例如Web浏览器)发送的HTTP请求,并返回网页以响应客户端,Web服务器通常提供html文档以及图像,样式表和脚本。Web应用架构Web应用程序通常分为四层-Client         -该层由Web浏览器,移动浏览器或可以向Web服务器......
  • Docker 学习笔记 - 4
    容器数据卷1.容器数据卷(1)是什么容器删除后数据自然也就没有了,所以用卷来保存数据。容器数据卷功能是持久化和数据共享。卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过UnionFileSyste提供一些用于持续存储或共享数据的特性。......
  • 【Dynamics365-Finance&Operations学习】Chain of Command Feature使用方法与使用场景
    前提微软在PlatformUpdate9之后引入了ChainofCommand(CoC),通过支持像Public和Protected类型的拓展,来为技术顾问和编程人员减少过度分层(overlayering)。在PU15(Dynamic365的某一版本)中,在Form、Table和Class的CoC已经被实现,但在表单数据源(FormDataSource)和表单数据字段(Formdat......
  • STM32CubeMX教程20 SPI - W25Q128驱动
    1、准备材料开发板(正点原子stm32f407探索者开发板V2.4)STM32CubeMX软件(Version6.10.0)野火DAP仿真器keilµVision5IDE(MDK-Arm)ST-LINK/V2驱动XCOMV2.6串口助手逻辑分析仪nanoDLA2、实验目标使用STM32CubeMX软件配置STM32F407开发板的SPI1与W25Q128芯片通信,以轮询方式读......
  • 在 SpringBoot 项目中使用 MDC 实现日志 traceId 的统一
    前言在项目中,对于每一次请求,我们都需要一个traceId将整个请求链路串联起来,这样就会很方便我们根据日志排查问题。但是如果每次打印日志都需要手动传递traceId参数,也会很麻烦,MDC就是为了解决这个场景而使用的。注:这里我们使用slf4j+logbacklogback配置logback.xml......
  • CF-240-F-线段树
    240-F题目大意给定一个长为\(n\)的字符串,由小写字母组成。由\(m\)次操作,每次操作给定一个区间\([l,r]\),要求你把区间中的字符进行重新排列,要求重排后的子串是字典序最小的回文串,如果无法得到回文串则忽略这次操作。输出\(m\)次操作之后的字符串。Solution涉及区间操作,考虑用......
  • Git必知必会基础(10):远程冲突(conflicts)解决--merge
     本系列汇总,请查看这里:https://www.cnblogs.com/uncleyong/p/10854115.html数据准备重新克隆 日志 远程分支qzcsbj.txt内容 commitid 其他人提交模拟其他人对master做了提交:直接gitee上修改文件并提交 新的commitid 本地提交本地分支修改qzcsbj.t......
  • C#学习笔记-类与名称空间
    1.类和对象  类是一个数据结构,将字段和方法组合在一个单元中。类为动态创建实例提供了定义,类的实例化称为对象。C#中的类同样支持继承和多态。C#是完全面向对象的语言,程序本身就是一个类。  如下所示,程序的入口点Main()方法包含在Program类中(与C++不同),类的实例使用new运......