蓝桥杯嵌入式学习笔记
用博客来记录一下参加蓝桥杯嵌入式第十六届省赛的学习经历
- 工具
- 环境准备
- cubemx配置
- 外部高速时钟使能
- 设置串口
- 时钟配置
- 项目配置
- keil配置
- 烧录方式
- 注意
- 代码规范
- 头文件配置
- 模块
- led
- cubemx配置
- keil代码
- 实现点亮一只灯
- 实现具体操作的灯,以及点亮还是熄灭
- 按键
- cubemx配置
- keil代码
- LCD
- keil代码
- 引脚冲突问题
- LED闪烁
- cubemx配置
- keil代码
- 按键长按
- cubemx配置
- keil代码
- LCD高亮显示
- keil代码
- PWM输出
- 计算公式
- cubemx配置
- keil代码
- 输入捕获测量引脚输出PWM波周期
- 原理图
- 要求:用PA7来测量PA1生成PWM波的频率
- cubemx配置
- keil代码
- 输入捕获测量555定时器频率
- 原理图
- cubemx配置
- keil代码
- ADC测量
- 原理图
- cubemx配置
- keil代码
- 串口发送和接收
- 原理图
- cubemx配置
- keil代码
- 利用定时器进行串口不定长数据接收
- 原理
- cubemx配置
- keil代码
- EEPROM读写
- 原理
- keil代码
工具
keil5,stm32cube
环境准备
根据赛事方提供的板子来选择cubemx上的器件
cubemx配置
外部高速时钟使能
设置串口
时钟配置
时钟配置为24MHZ因为外部晶振为24MHZ,其余的暂时不清楚原因
项目配置
配置为MDK
需要注意,固件地址需要设置为下载解压后的文件地址(提前从数据包中下载)
勾选生成.c.h文件
注意一下,下载好软件后,要解压固件包,然后在help中设置地址
keil配置
烧录方式
烧录设置
要是没有芯片包,需要从赛事数据包中解压,会自动生成
keil代码自动补全
点击edit,configraution选择跟编译相关的Text Completion,然后勾线第三个
注意
代码需要写入begin - end之间
代码规范
新建code文件夹
右键CMSIS,点击Manage Project,新建一个文件夹
点击魔术棒,c++,include path,添加文件夹路径
然后添加fun.c,fun.h,headfile.h 三个文件
头文件可能显示不出来,所以需要添加existing file 再勾选all file,即可添加
头文件配置
headfile.h
fun.h
fun.c
main.c
模块
led
通过观察开发板led电路图可以发现,led的的引脚控制由PC8~15低电平点亮,同时PD2锁存器控制开关,需要置高电平
cubemx配置
将PC8~15设置为输出,PD2设置为输出
在GPIO配置中,将引脚全部配置为高电平,使得上电时LED灭
keil代码
实现点亮一只灯
fun.c主要代码
void led_show()
{HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);}
fun.h代码
void led_show(void);
main.c代码(需要在主函数内)
led_show();
实现具体操作的灯,以及点亮还是熄灭
fun.c代码
void led_show(uint8_t led, uint8_t mode)
{HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);if(mode)HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 << (led - 1), GPIO_PIN_RESET); //GPIO_PIN_8的二进制代码为0000 0001 0000 0000 GPIO_PIN_9的二进制代码为0000 0010 0000 0000,所以用左移移位符elseHAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 << (led - 1), GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);}
fun.h代码(需要加上那个头函数)
#include "stm32g4xx.h" // Device headervoid led_show(uint8_t led, uint8_t mode);
main.c代码(灯1, 4,8亮)
led_show(1, 1);led_show(4, 1);led_show(8, 1);
按键
原理图,如图,需要将PB0~2,PA0配置为上拉输入模式。按下为低电平,松开为高电平
cubemx配置
keil代码
fun.c代码
void key_scan()
{B1_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);B2_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);B3_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);B4_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);if(B1_state == 0 && B1_last_state == 1)//°´¼üB1°´ÏÂ{led_show(1, 1);}if(B2_state == 0 && B2_last_state == 1)//°´¼üB1°´ÏÂ{led_show(1, 0);}if(B3_state == 0 && B3_last_state == 1)//°´¼üB1°´ÏÂ{led_show(2, 1);}if(B4_state == 0 && B4_last_state == 1)//°´¼üB1°´ÏÂ{led_show(2, 0);}B1_last_state = B1_state;B2_last_state = B2_state;B3_last_state = B3_state;B4_last_state = B4_state;}
fun.h代码
void key_scan(void);//里面没有这个void会有waring,但影响似乎不大
main.c代码
同样放入while循环中
LCD
首先在赛事方提供的数据包中找到液晶驱动参考程序,HAL库版本,找到lcd.c,font.h,lcd,h,复制到code文件夹,打开keil工程文件,添加这三个文件
初始准备
main.c函数
headfile.h函数
keil代码
实现了在第一行显示字符,按键按下时,第三行数字变化的功能
fun.c代码
#include "headfile.h"int count = 0;void led_show(uint8_t led, uint8_t mode)
{HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);if(mode)HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 << (led - 1), GPIO_PIN_RESET);elseHAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 << (led - 1), GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);}uint8_t B1_state;
uint8_t B1_last_state;
uint8_t B2_state;
uint8_t B2_last_state;
uint8_t B3_state;
uint8_t B3_last_state;
uint8_t B4_state;
uint8_t B4_last_state;void key_scan()
{B1_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);B2_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);B3_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);B4_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);if(B1_state == 0 && B1_last_state == 1)//°´¼üB1°´ÏÂ{count ++;}if(B2_state == 0 && B2_last_state == 1)//°´¼üB1°´ÏÂ{count --;}if(B3_state == 0 && B3_last_state == 1)//°´¼üB1°´ÏÂ{led_show(2, 1);}if(B4_state == 0 && B4_last_state == 1)//°´¼üB1°´ÏÂ{led_show(2, 0);}B1_last_state = B1_state;B2_last_state = B2_state;B3_last_state = B3_state;B4_last_state = B4_state;}char text[20]; //linemax = 20void lcd_show()
{sprintf(text, "zlfsgdsg");//¿ÉÒÔµ÷Õû×Ö·û´®Î»Ö㬵«ÊÇ×î¶à20¸ö×Ö·ûLCD_DisplayStringLine(Line0, (uint8_t *)text);sprintf(text, " count: %d ", count);LCD_DisplayStringLine(Line3, (uint8_t *)text);}
fun.h代码
#ifndef _fun_h
#define _fun_h#include "stm32g4xx.h" // Device headervoid led_show(uint8_t led, uint8_t mode);void key_scan(void);void lcd_show(void);#endif
main.c代码
引脚冲突问题
lcd和led的引脚有冲突
解决办法:将PD2引脚提前置低电平,这样数据就不能传入led,led就不会点亮了,但是下次点亮led时依旧会出现这样的问题,所以需要将所有用到的LCD.C函数加上
uint16_t temp = GPIOC->ODR;
GPIOC->ODR = temp;
解决方法如下
main.c (在初始化部分)
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
lcd.c (部分代码)
问题成功解决!
LED闪烁
两个重要参数:PSC,ARR
其中系统频率f为80MHZ,如果要让T=1,则可令ARR = 9999,PSC = 7999;即可确定定时周期为1
初始化
在headfile.h文件中添加tim.h文件头
main.c
cubemx配置
需要配置定时器,正常使用通用定时器TIM2即可,重点是修改PSC和ARR
生成代码后可发现多了tim.c函数,找到stm32g4xx_hal_tim.h文件里面的call_back回调函数
将其复制到fun.c中
keil代码
在fun.c中定义一个变量
uint8_t led_mode;
按键长按
原理,用一个计数器cnt(取10000)计时1s,20000对应2s,5000对应0.5s来计时,达到识别按键长按的目的
cubemx配置
此时TIM3不使能!!
keil代码
fun.c代码
uint8_t B1_state;
uint8_t B1_last_state;
uint8_t B2_state;
uint8_t B2_last_state;
uint8_t B3_state;
uint8_t B3_last_state;
uint8_t B4_state;
uint8_t B4_last_state;void key_scan()
{B1_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0);B2_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);B3_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2);B4_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);if(B1_state == 0 && B1_last_state == 1)//°´¼üB1°´ÏÂ{TIM3->CNT = 0;}else if(B1_state == 0 && B1_last_state == 0) //°´¼üB1Ò»Ö±°´ÏÂ{if(TIM3->CNT >= 10000)//°´¼üB1³¤°´{count++;}}else if (B1_state == 1 && B1_last_state == 0)//°´¼üB1ËÉ¿ª{if(TIM3->CNT < 10000)//°´¼üB1¶Ì°´{count += 2;}}if(B2_state == 0 && B2_last_state == 1)//°´¼üB1°´ÏÂ{count --;}if(B3_state == 0 && B3_last_state == 1)//°´¼üB1°´ÏÂ{led_show(2, 1);}if(B4_state == 0 && B4_last_state == 1)//°´¼üB1°´ÏÂ{led_show(2, 0);}B1_last_state = B1_state;B2_last_state = B2_state;B3_last_state = B3_state;B4_last_state = B4_state;}
main.c代码
需要注意!给TIM3使能,但因为不是中断,是定时器,所以不用IT
LCD高亮显示
其实就是调用 LCD_SetBackColor(Color);这个函数,把背景颜色改成黄色
keil代码
定义变量
uint8_t lcd_highshow;
按键b1按下时
lcd_highshow ++;lcd_highshow %= 3;
逻辑流程
应该蛮简单的,就不写注释了
void lcd_show()
{sprintf(text, "zlfsgdsg");//¿ÉÒÔµ÷Õû×Ö·û´®Î»Ö㬵«ÊÇ×î¶à20¸ö×Ö·ûLCD_DisplayStringLine(Line0, (uint8_t *)text);if(lcd_highshow == 0){LCD_SetBackColor(Yellow);sprintf(text, " count: %d ", count);LCD_DisplayStringLine(Line3, (uint8_t *)text);LCD_SetBackColor(Black);sprintf(text, " txysgdmn ");LCD_DisplayStringLine(Line4, (uint8_t *)text);sprintf(text, " baozi ");LCD_DisplayStringLine(Line5, (uint8_t *)text); }else if(lcd_highshow == 1){sprintf(text, " count: %d ", count);LCD_DisplayStringLine(Line3, (uint8_t *)text);LCD_SetBackColor(Yellow);sprintf(text, " txysgdmn ");LCD_DisplayStringLine(Line4, (uint8_t *)text);LCD_SetBackColor(Black);sprintf(text, " baozi ");LCD_DisplayStringLine(Line5, (uint8_t *)text); }
PWM输出
一般要求:让PA1输出频率为1000HZ,占空比为50%的方波
计算公式
cubemx配置
keil代码
在生成代码后,发现一个问题:文件中没有头文件!
后面找到解决办法, 编译之后,就能知道每个文件依赖于哪些头文件!还是第一次遇到这种问题
先在main.c函数中将定时器使能
这个函数在头文件里找–stm32g4xx_hal_tim.h
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
设置占空比
TIM2->CCR2 = 50;
原理图(抄袭版),不懂的话看嵌入式的书去
输入捕获测量引脚输出PWM波周期
原理图
要求:用PA7来测量PA1生成PWM波的频率
需要用杜邦线连接PA7和PA1.
cubemx配置
这里PA7用TIM17或者TIM2都行,我就根据视频来了
使能定时器
keil代码
为了省事,将code文件复制到这个工程目录下,记得在main.c文件中添加头文件定义
main.c函数
使能中断17
HAL_TIM_IC_Start_IT(&htim17, TIM_CHANNEL_1);
fun.c代码
参考着原理图一起理解
#include "headfile.h"char text[20]; uint32_t fre, capture_value;void lcd_show()
{sprintf(text, "zlfsgdsg");//¿ÉÒÔµ÷Õû×Ö·û´®Î»Ö㬵«ÊÇ×î¶à20¸ö×Ö·ûLCD_DisplayStringLine(Line0, (uint8_t *)text);sprintf(text, " fre:%d ", fre);LCD_DisplayStringLine(Line3, (uint8_t *)text);}void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM17){capture_value = TIM17->CCR1;TIM17->CNT = 0;fre = 80000000/(80*capture_value);}}
main.c代码
注意不要忘记了给LCD初始化
/* USER CODE BEGIN 2 */LCD_Init();LCD_Clear(Black);LCD_SetBackColor(Black);LCD_SetTextColor(White);HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);TIM2->CCR2 = 50;HAL_TIM_IC_Start_IT(&htim17, TIM_CHANNEL_1);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){lcd_show();/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
输入捕获测量555定时器频率
实现效果:能测量出两个信号发生器输出的PWM波的频率,两个频率可以通过R39,和R40调节
原理图
cubemx配置
将PA15设置为TIM2_CH1,PB4设置为TIM16_CH1;
分别将两个定时器设置为输入捕获模式,PCC设置为80-1,并且使能
keil代码
main.c
需要注意,不要忘记了LCD初始化,不要忘记了中断使能,不要忘记了把lcd_show函数放到循环里
/* USER CODE BEGIN 2 */LCD_Init();LCD_Clear(Black);LCD_SetBackColor(Black);LCD_SetTextColor(White);HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);HAL_TIM_IC_Start_IT(&htim16, TIM_CHANNEL_1);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){lcd_show();/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
&&& 不要忘记了添加头文件!
#include "headfile.h"
fun.c函数
具体逻辑,我现在看是蛮简单的,不管了,吃饭去了,自己悟去吧
#include "headfile.h"char text[20]; uint32_t fre1, capture_value1, fre2, capture_value2 ;void lcd_show()
{sprintf(text, "zlfsgdsg");//¿ÉÒÔµ÷Õû×Ö·û´®Î»Ö㬵«ÊÇ×î¶à20¸ö×Ö·ûLCD_DisplayStringLine(Line0, (uint8_t *)text);sprintf(text, " R39_fre1:%d ", fre1);LCD_DisplayStringLine(Line2, (uint8_t *)text);sprintf(text, " R40_fre2:%d ", fre2);LCD_DisplayStringLine(Line4, (uint8_t *)text);}void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM16)// R39{capture_value1 = TIM16->CCR1;TIM16->CNT = 0;fre1 = 80000000/(80*capture_value1);}if(htim->Instance == TIM2)//R40{capture_value2 = TIM2->CCR1;TIM2->CNT = 0;fre2 = 80000000/(80*capture_value2);}}
ADC测量
原理图
通过R37和R38两个旋钮,测量AD的电压值
cubemx配置
分别对引脚PB15和PB12进行配置。
keil代码
记得在headfile.h文件中添加ADC头文件
fun.c代码
#include "headfile.h"char text[20];
void lcdshow()
{sprintf(text, " zlfsgdsg ");LCD_DisplayStringLine(Line0, (uint8_t *)text);HAL_ADC_Start(&hadc1); uint32_t adc_value = HAL_ADC_GetValue(&hadc1); //R38sprintf(text, " value:%d ", adc_value);LCD_DisplayStringLine(Line3, (uint8_t *)text);}
main.c
记得将LCD初始化,然后在主函数中调用lcdshow();
即可在lcd中实时读取adc1的值
keil代码2
若是要读取两个ad的电压值
fun.c代码
#include "headfile.h"char text[20];
void lcdshow()
{sprintf(text, " zlfsgdsg ");LCD_DisplayStringLine(Line0, (uint8_t *)text);sprintf(text, " R37_volt:%.2f ", get_vol(&hadc2));LCD_DisplayStringLine(Line3, (uint8_t *)text);sprintf(text, " R38_volt:%.2f ", get_vol(&hadc1));LCD_DisplayStringLine(Line5, (uint8_t *)text);}double get_vol(ADC_HandleTypeDef *hadc)
{HAL_ADC_Start(hadc); uint32_t adc_value = HAL_ADC_GetValue(hadc); //R38return 3.3*adc_value/4096; //因为AD是12位,所以ad最大值是4096}
fun.h
void lcdshow(void);double get_vol(ADC_HandleTypeDef *hadc);
串口发送和接收
原理图
cubemx配置
keil代码
串口发送
main.c代码
记得在前面添加头文件
while (1){char text01[20];sprintf(text01, "zlfsgdgs\r\n");HAL_UART_Transmit(&huart1, (uint8_t *)text01, sizeof(text01), 50);HAL_Delay(1000);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
串口接收
fun.c代码
#include "headfile.h"uint8_t rec_data;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){HAL_UART_Transmit(huart, &rec_data, 1, 50);HAL_UART_Receive_IT(huart, &rec_data, 1);}}
fun.h代码
加一个外部变量定义
extern uint8_t rec_data;
main.c代码
利用定时器进行串口不定长数据接收
原理
cubemx配置
主要是把波特率设置为9600
keil代码
main.c
把定时器使能!!!&&调用函数
fun.c函数
#include "headfile.h"char send_buff[20];
uint8_t rec_data, count;
uint8_t rec_flag;
uint8_t rec_buff[20];void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance == USART1){//HAL_UART_Transmit(huart, &rec_data, 1, 50);TIM4->CNT = 0;rec_flag = 1;rec_buff[count] = rec_data;count ++;HAL_UART_Receive_IT(huart, &rec_data, 1);}}void uart_data_rec()
{if(rec_data){if(TIM4->CNT > 15){if(rec_buff[0] == 'z' && rec_buff[1] == 'l' && rec_buff[2] == 'f'){sprintf(send_buff, "zlf\r\n");HAL_UART_Transmit(&huart1, (uint8_t *)send_buff, sizeof(send_buff), 50);}else if(rec_buff[3] == 's' && rec_buff[4] == 'g' && rec_buff[5] == 'd'){sprintf(send_buff, "sgd\r\n");HAL_UART_Transmit(&huart1, (uint8_t *)send_buff, sizeof(send_buff), 50);}else if(rec_buff[6] == 's' && rec_buff[7] == 'g'){sprintf(send_buff, "sgd\r\n");HAL_UART_Transmit(&huart1, (uint8_t *)send_buff, sizeof(send_buff), 50);}else{sprintf(send_buff, "error\r\n");HAL_UART_Transmit(&huart1, (uint8_t *)send_buff, sizeof(send_buff), 50);}rec_flag = 0;for(int i=0; i<count; i++)rec_buff[i] = 0;count = 0;}}}
fun.h
headfile.h
要添加usart.h的头文件
EEPROM读写
原理
原理就不说了,学嵌入式I2C的时候学了挺久
keil代码
i2c_hal_c
void eeprom_write(uint8_t addr, uint8_t data)
{I2CStart();I2CSendByte(0xa0);I2CWaitAck();I2CSendByte(addr);I2CWaitAck();I2CSendByte(data);I2CWaitAck();I2CStop();HAL_Delay(20);}uint8_t eeprom_read(uint8_t addr)
{I2CStart();I2CSendByte(0xa0);I2CWaitAck();I2CSendByte(addr);I2CWaitAck();I2CStop();I2CStart();I2CSendByte(0xa1);I2CWaitAck();uint8_t data = I2CReceiveByte();I2CSendNotAck();I2CStop();return data;
}
i2c_hal_h代码
主要就是添加两个文件
void eeprom_write(uint8_t addr, uint8_t data);
uint8_t eeprom_read(uint8_t addr);
main.c代码
相关文章:
蓝桥杯嵌入式学习笔记
用博客来记录一下参加蓝桥杯嵌入式第十六届省赛的学习经历 工具环境准备cubemx配置外部高速时钟使能设置串口时钟配置项目配置 keil配置烧录方式注意代码规范头文件配置 模块ledcubemx配置keil代码实现点亮一只灯实现具体操作的灯,以及点亮还是熄灭 按键cubemx配置k…...
0201-jsx语法基础-jsx-仿低代码平台项目
文章目录 1.jsx标签2.jsx属性3.jsx 事件3.1 声明事件3.2 使用事件(对象) 4. typescript类型基础4.1 类型声明4.2 事件函数传递自定义参数 5.插入js变量6. 条件判断7. 循环结语 1.jsx标签 jsx标签与html标签区别: 首字母大小写 大写是自定义组…...
在MCU工程中优化CPU工作效率的几种方法
在嵌入式系统开发中,优化 CPU 工作效率对于提升系统性能、降低功耗、提高实时性至关重要。Keil 作为主流的嵌入式开发工具,提供了多种优化策略,包括 关键字使用、内存管理、字节对齐、算法优化 等。本文将从多个方面介绍如何在 Keil 工程中优…...
Elasticsearch 的搜索功能
Elasticsearch 的搜索功能 建议阅读顺序: Elasticsearch 入门Elasticsearch 搜索(本文)Elasticsearch 搜索高级Elasticsearch 高级 1. 介绍 使用 Elasticsearch 最终目的是为了实现搜索功能,现在先将文档添加到索引中,…...
【鸿蒙5.0】向用户申请麦克风授权
#效果图 步骤 在 config.json 里声明权限:在项目的 config.json 文件中添加麦克风权限的声明,告知系统应用需要使用该权限。检查权限状态:在代码里检查应用是否已经获得了麦克风权限。请求权限:若应用未获得麦克风权限࿰…...
数据结构与算法分析:树与哈希表(一)
遇到的问题,都有解决方案,希望我的博客能为你提供一点帮助。 一、概述 背景:链表处理大量数据时,线性访问耗时多。二叉查找树多数操作平均运行时间为 O (log N),相对于链表树更加高效。 1.预备知识 1.1. 树的定义与…...
VBA第三十四期 VBA中怎么用OnKey事件
我们在VBA设计中经常需要使用到OnKey方法,特别是在窗口设计中比如我们想用到翻页按键,则就可以来建立一个OnKey事件。Setup_OnKey过程运行以后,就会达到最终效果,按PgDn键会将指针下移一行,按PgUp键会将指针上移一行。…...
HarmonyOS NEXT开发进阶(十五):日志打印 hilog 与 console.log 的区别
文章目录 一、前言二、两者区别对比三、HiLog 详解四、拓展阅读 一、前言 在日常开发阶段,日志打印是调试程序非常常用的操作,在鸿蒙的官方文档中介绍了hilog这种方式,前端转过来的开发者发现console.log也可以进行日志打印,而且…...
Skynet 框架中 gateserver、gate、watchdog 的关系
一、概述 在 Skynet 框架的网络通信架构中,gateserver、gate、watchdog 是三个核心组件,共同实现客户端连接的监听、管理和业务逻辑的分发。其设计目标是通过分层解耦,提升网络层的稳定性与业务逻辑的灵活性。 二、组件职责 1. gateserve…...
第11章:优化I/O_《C++性能优化指南》_notes
第十一章核心知识点详解 11.1 读取文件的优化技巧 重点:减少内存分配、使用大缓冲区、优化函数调用链。 难点:理解系统调用开销与缓冲区大小的权衡。 代码示例与详解 示例1:使用高效函数签名和减少内存分配 #include <fstream> #inc…...
【C++初阶】--- 内存管理
1.C/C内存分布 我们一般说的32位机器和64位机器指的是虚拟空间的大小,也就是进程地址空间的大小,32位机器下,进程地址空间的大小是232个字节,也就是4G,64位机器下,进程地址空间的大小是264个字节,大概160亿…...
使用 Ansys Discovery 可视化液体池中的水流
了解 ANSYS Discovery:设计领域的变革者 ANSYS Discovery 是一款功能强大的软件工具,能够彻底改变设计流程。借助其先进的仿真功能,工程师现在可以在设计投入生产之前更深入地了解其设计。通过使用 ANSYS Discovery,设计师可以快…...
网络安全-网络安全基础
一、网络安全概述 TCP/IP协议定义了一个对等的开放性网络,使得连接到这个网络中的所有用户都可能面临来自网络中的恶意的破坏和攻击。这些攻击通过网络通信协议、网络应用协议甚至物理传输链路来实现。主要针对于软件和硬件进行攻击。那在互联网上如何保证自己的安…...
YOLOv8+ Deepsort+Pyqt5车速检测系统
该系统通过YOLOv8进行高效的目标检测与分割,结合DeepSORT算法完成目标的实时跟踪,并利用GPU加速技术提升处理速度。系统支持模块化设计,可导入其他权重文件以适应不同场景需求,同时提供自定义配置选项,如显示标签和保存…...
QML中的附加属性和附加信号处理程序
QML中的附加属性和附加信号处理程序 在QML中,附加属性(Attached Properties)和附加信号处理程序(Attached Signal Handlers)是特殊类型的属性和信号,它们由附加类型(Attached Types)提供,而不是由对象本身直接提供。 什么是附加的(Attached…...
爱普生FC-135晶振5G手机的极端温度性能守护者
在5G时代,智能手机不仅需要高速率与低延迟,更需在严寒、酷暑、振动等复杂环境中保持稳定运行。作为 5G 手机的核心时钟源,爱普生32.768kHz晶振FC-135凭借其宽温适应性、高精度稳定性与微型化设计,成为5G手机核心时钟源的理想选择&…...
GPT Workspace体验
GPT Workspace是一款将强大的自然语言处理模型(如 ChatGPT 和 Gemini)集成到 Google Workspace 应用(如 Google Docs, Sheets, Slides, Gmail 和 Drive)中的工具或插件。它的目标是提升用户在日常办公中的效率和创造力。 以下是对…...
Teleport 和 Set Actor location的区别
Teleport 和 Set Actor Location 都可以用于移动一个 Actor 的位置,但它们在底层逻辑和适用场景上有显著区别. 1. Set Actor Location 功能: 直接设置 Actor 的位置,不重置物理状态(如速度、动量)。 行为特点…...
“GPU 挤不动了?”——聊聊基于 GPU 的计算资源管理
“GPU 挤不动了?”——聊聊基于 GPU 的计算资源管理 作者:Echo_Wish “老板:为什么 GPU 服务器卡得跟 PPT 一样?” “运维:我们任务队列爆炸了,得优化资源管理!” 在 AI 训练、深度学习、科学计算的场景下,GPU 计算资源已经成为香饽饽。但 GPU 服务器贵得离谱,一台 A…...
解决前端项目中无法识别 .node 文件的依赖安装问题
解决前端项目中无法识别 .node 文件的依赖安装问题 问题描述 在 macOS 系统(M1 Pro 芯片),使用 Node.js 版本 20.9.0 和 Vue 3 的环境下,项目启动过程中遇到了以下错误: [ERROR] No loader is configured for "…...
Gateway实战入门(四)、断言-请求头以及请求权重分流等
spring cloud-Gateway:断言-请求头以及请求权重分流等 一、断言Header信息要求项目前置环境要求案例一、断言-请求头信息-匹配X-Request-Id1、配置文件及代码2、测试 案例二、断言-请求头信息-匹配API版本场景主要配置信息 案例三、断言-请求头信息:匹配…...
YOLOv11模型的常见处理
一.数据准备: 1.数据集格式: 目录结构示例: datasets/├── images/│ ├── train/ # 训练图片│ └── val/ # 验证图片└── labels/├── train/ # 训练标签└── val/ # 验证标签 每张图片对应一个 .txt 标注文件…...
conda 清除 tarballs 减少磁盘占用 、 conda rename 重命名环境、conda create -n qwen --clone 当前环境
🥇 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 🎉 声明: 作为全网 AI 领域 干货最多的博主之一,❤️ 不负光阴不负卿 ❤️ 文章目录 conda clean --tarballsconda rename 重命名环境conda create -n qwen --clone …...
无线局域网
1.5G支持中低频和高频频段, 2.网络切片是指从应该网络中选取特定的特性和功能 3.WLAN广义指无线电波,激光,红外线等无线信号代替有线局域网中的部分或者全部传输介质所构成的网络。 4.802.11运行在2.4GHz ISM 频段,采用扩频通信…...
百人会上的蔚小理与「来的刚刚好」的雷军
这就是2025百人会上的蔚小理,努力的李斌、宣扬飞行汽车的何小鹏与大讲开源的李想。那么小米汽车的模式是什么呢?站在蔚小理的肩上。 这就是2025百人会上的蔚小理,努力的李斌、宣扬飞行汽车的何小鹏与大讲开源的李想。那么小米汽车的模式是什么…...
现代优雅杂志海报徽标设计手写英文字体安装包 Attomes – Brush Handwritten Font
Attomes 简介 – Brush 手写字体 此字体是一种精致、优雅、流畅的手写字体。它有一个美丽而独特的连字混合字母,因此作者用一个小漩涡嵌入来撰写它,从而形成现代字体,并准备好通过为您的下一个设计项目添加优雅和独特的风格来发表声明。将其…...
Java进阶——静态代理与动态代理
代理模式是一种常用的设计模式,为其他对象提供一种代理以控制对这个对象的访问。代理模式就像是一个中间人,客户端通过代理来间接访问目标对象,可以在不修改目标对象的基础上,对目标对象的功能进行增强或扩展。代理模式主要分为静…...
【多线程】进阶
目录 一、CAS 什么是 CAS CAS 伪代码 CAS 有哪些应用 实现原子类 CAS 是怎么实现的 如何通过 CAS 实现的原子类 CAS 的 ABA 问题 什么是 ABA 问题 ABA 问题引来的 BUG 正常的过程 异常的过程 解决方案 📝相关面试题 二、JUC(java.util.concurrent)的…...
MFC中字符串string类型和CString类型互转方法
文章目录 一、CString 转 std::string1. Unicode项目(_UNICODE 已定义)2. 多字节项目(_MBCS 已定义) 二、std::string 转 CString1. Unicode项目(_UNICODE 已定义)2. 多字节项目(_MBCS 已定义&a…...
工作记录 2017-03-13
工作记录 2017-03-13 序号 工作 相关人员 1 修改邮件上的问题。 开始处理操作日志部分。 测试了C#和MySql的连接。 更新RD服务器。 郝 更新的问题 1、 修改了CMS1500的打印,NDC的内容用了小的字体。 2、在Cliams List中可以查看Job的Notes。 3、Payment Po…...
Linux 配置NFS服务器
1. 开放/nfs/shared目录,供所有用户查阅资料 服务端 (1)安装nfs服务,nfs-utils包中包含rpcbind(rpc守护进程) [rootnode1-server ~]# yum install -y nfs-utils # nfs-utils包中包含rpcbind [rootnode…...
Linux《进程概念(上)》
在之前的Linux学习当中我们已经了解了基本的Linux指令以及基础的开发工具的使用,那么接下来我们就要开始Linux当中一个非常重要的部分的学习——进程,在此进程是我们之后Linux学习的基础,并且通过进程的学习会让我们了解更多的操作系统的相关…...
游戏开发中的贝塞尔曲线:感受丝滑的数学之美
这是一篇vip文章,如果你还不是vip,可以移步https://www.ilikexff.cn/articles/165免费阅读。 介绍 贝塞尔曲线是计算机图形学中最重要的概念之一,以其在表示曲线时的灵活性和精确性而闻名。广泛应用于计算机图形学、动画、路径规划等领域的数学曲线。 贝塞尔曲线的数学原理基…...
Java【多线程】(6)定时器
目录 1.前言 2.正文 2.1库中定时器 2.2手搓定时器 3.小结 1.前言 哈喽大家好呀,今天继续给大家分享Java中定时器的学习,正文包括定时器的三种实现方式,正文如下。 2.正文 在 Java 中,定时器(Timer)…...
Epub转PDF软件Calibre电子书管理软件
Epub转PDF软件:Calibre电子书管理软件 一款好用的电子书管理软件,可快速导入电脑里的电子书并进行管理,支持多种格式,阅读起来非常方便。同时也有电子书格式转换功能。 第一步:添加电子书 将需要转换的电子书添加到…...
使用FastExcel时的单个和批量插入的问题
在我们用excel表进行插入导出的时候,通常使用easyexcel或者FastExcel,而fastexcel是easy的升级版本,今天我们就对使用FastExcel时往数据库插入数据的业务场景做出一个详细的剖析 场景1 现在我们数据库有一张组织表,组织表的字段…...
nginx https配置
一.https配置 HTTPS 协议是由HTTP 加上TLS/SSL 协议构建的可进行加密传输、身份认证的网络协议,主要通过数字证书、加密算法、非对称密钥等技术完成互联网数据传输加密,实现互联网传输安全保护。 1.生成证书 openssl genrsa -des3 -out server.key 20…...
git --- cherry pick
git --- cherry pick cherry pick cherry pick Cherry Pick 是 Git 中的一个操作,它允许你选择某个分支的某次(或多次)提交,并将其应用到当前分支,而不会合并整个分支的所有更改。 cherry pick 的作用 只提取某个特定的…...
虚拟机安装linux系统无法上网的解决方法
在虚拟环境中运行Linux系统时,有时会遇到网络连接问题,特别是在使用虚拟机软件如VMware或VirtualBox时。本文将详细介绍一种针对“虚拟机安装Linux系统无法上网”问题的解决方案,以CentOS 6.5为例,适用于其他基于NAT模式的虚拟机环…...
北大人工智能研究院朱松纯:“中国的AI叙事” 存在认知偏差
3月29日,在2025中关村论坛通用人工智能论坛上,北京通用人工智能学院院长,北京大学人工智能研究院、智能学院院长朱松纯表示,目前,行业对AI的讨论几乎被大模型能力所占据,而基础学科、原始创新与智能本质的研…...
Java高频面试之集合-20
hello啊,各位观众姥爷们!!!本baby今天来报道了!哈哈哈哈哈嗝🐶 面试官:讲讲 HashSet 的底层实现? HashSet 是 Java 集合框架中用于存储唯一元素的高效数据结构,其底层实…...
使用Qemu模拟32位ARM系统
一、环境 实验环境如下: 主机:x86_64 操作系统:Ubuntu 20.04.6 LTS Qemu版本:QEMU emulator version 4.2.1 Linux内核版本:linux-4.4.240 Busybox版本:busybox-1.35.0二、前置准备 下载 linux-4.4.240 源…...
【初阶数据结构】栈
文章目录 一、概念与结构 二、栈的实现 栈的定义 1.初始化 2.入栈 3.判断栈是否为空 4.出栈 5.取栈顶元素 6.获取栈中有效元素个数 2.销毁 三、完整码源 总结 一、概念与结构 栈: 一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据…...
docker-compose部署prometheus+grafana+node_exporter
目录 docker-compose文件 配置文件 文件层级关系,docker-compose和配置文件位于同级目录 node_exporter页面json文件 涉及离线包 一.docker-compose文件 [rootsulibao prometheus]# cat docker-compose.yml version: 3services:prometheus:image: registry.c…...
maya调整全局关节显示大小
请按以下步骤操作: 在 Maya 主菜单栏中,找到 Display (显示) 菜单。 在 Display 菜单下,找到 Animation (动画) 子菜单。 在 Animation 子菜单中,点击 Joint Size... (关节大小...)。 这时会弹出一个小窗口或者直接在界面上出现…...
“屏幕“的实现_程序中如何将数据映射到硬件_C++实战
前言 程序里的数据,最后都需要将数据对象写入硬件.C/C最大的优势体现也是在这里,他既是高级语言方便被程序员使用,又能和硬件沟通. 引入 以"屏幕"的实现,总结数据映射到硬件的代码写法 分析 软件部分 1.屏幕是数据对象---一切都是数据,一切都是对象;数据有类型,屏…...
R --- Error in library(***) : there is no package called ‘***’ (服务器非root用户)
步骤 步骤一:在自己目录下创建R包安装路径步骤二:配置用户本地的R库路径步骤三:安装缺失的包(在终端)步骤四:验证安装 步骤一:在自己目录下创建R包安装路径 mkdir -p ~/R_libs步骤二࿱…...
Go中的逃逸分析
什么是逃逸? 逃逸是指一个变量本来应该分配在栈(stack)上,但由于某些原因,最终被分配到了堆(heap)上。 类比: 栈就像一个临时的快餐盒,用来存放短期使用的数据。堆就像…...
解决 Android AGP 最新版本中 BuildConfig 报错问题
在最新版本的 Android Gradle Plugin (AGP) 中,Google 对构建系统做了不少改动,可能会导致一些与 BuildConfig 相关的问题。以下是常见问题及解决方案: 常见问题及修复方法 1. BuildConfig 类完全缺失 原因:AGP 8.0 默认不再为库模…...
Rollup系列之安装和入门
Rollup Rollup.js的主要用途是将小的代码片段编译成更大、更复杂的代码,例如库或应用程序。它特别适用于将ES模块编译成不同的模块形式,如AMD、CommonJS、UMD等,以便在不同的环境中使用。 Rollup的应用场景与好处: 插件或…...