蓝桥杯嵌入式比赛知识点合集(现在什么都有好吧)

2023-05-16

目录

  • 新建工程
  • LCD
    • sprintf
      • 格式
      • 输出百分号
    • 输出格式:%R
    • memset函数
    • LCD_DisplayStringLine函数
    • 嘀嗒定时器
    • 高亮
      • 行高亮
      • 一两个字符高亮
        • 单个字节高亮
          • 使用
        • 多个字节高亮
          • 使用
    • 行闪烁
        • 使用
  • LED
    • display函数
        • 注意:为了解决与LCD的冲突问题,需要改变lcd.c里的三个函数——
  • Time_Base
    • 中断服务函数
  • Buzzer
    • 使能
    • 配置GPIO
  • KEY
    • 变量调用
    • 注意宏定义运算表达式
    • Scan函数
    • Disp函数
      • 只考虑短按(单击)
      • 考虑长短按
  • E2PROM
    • 掉电不丢失
    • 写入数据函数
    • 读取多个数据
    • 多类型读写
    • 注意
  • RTC
    • 快速配置
  • ADC
    • 注意的点
  • PWM
    • 定时器通道引脚分布图表
    • 输出两路频率固定占空比可调的 PWM----文件名:PWM_Output
      • 快速配置
      • 设置占空比
      • 使用方法
    • 输出两路频率可调占空比可调的 PWM----文件名:OCToggle
      • 快速配置
      • 使用方法
        • 注意:
    • 捕获一路PWM的频率和占空比----文件名:PWM_Input
      • 快速配置
      • 使用方法
        • 注意:
    • 捕获两路PWM的频率和占空比
      • 思路
      • 代码
    • 串口与TIM2冲突问题
  • 串口
    • 基本知识
    • 使用
    • 闲时判断
    • 善用状态
  • C语言知识点
    • 字符与字符串
      • strcpy 复制
      • strcmp 比较
      • strlen 取长度(不包括结尾'\0')
      • strcat 追加拷贝
      • 注意
    • 提取字符串

新建工程

不推荐自己新建工程,直接用他给的例程,复制一份,然后加上一个bsp文件夹放自己新建的.h.c文件就行了,会方便很多。

LCD

sprintf

格式

sprintf((char*)buf,"   The Humam : %d   ",200);

注意是(char*)不是(char);
注意字符长度不能超过20(数组长度),否则LED不会亮。
长度最好写19个。
记得加上头文件"stdio.h"。



输出百分号

sprintf((char*) display_buf,"%d %% ",10);			//输出百分号:%

注:要打两个百分号才行。



输出格式:%R

%d 整型输出,%ld 长整型输出,

%o 以八进制数形式输出整数,

%x 以十六进制数形式输出整数,

%u 以十进制数输出 unsigned 型数据 (无符号数)。16进制转十进制非常有用。

%c 用来输出一个字符,

%s 用来输出一个字符串,

%f 用来输出实数,以小数形式输出,

%e 以指数形式输出实数,

%g 根据大小自动选 f 格式或 e 格式,且不输出无意义的零。



memset函数

memset(buf,0,20 * sizeof(uint8_t));

加头文件"string.h"。
memset 的用法详解



LCD_DisplayStringLine函数

LCD_DisplayStringLine(Line4,buf);

buf 只能是unsigned char类型。
在这里插入图片描述



嘀嗒定时器

配置了嘀嗒定时器一定要写中断服务程序,不然LCD不会起作用。



高亮

行高亮

/* 如果标志位为1,则让当前行高亮为绿色 */
if(lcd_light == 1)LCD_SetBackColor(Green);
sprintf((char*)Buf,"  Threshold 1: %02ucm  ",Threshold_Buf[0]);
LCD_DisplayStringLine(Line3,Buf);
memset(Buf,0,20*sizeof(uint8_t));
/* 使下一行仍为默认颜色 */
LCD_SetBackColor(Blue);


一两个字符高亮

单个字节高亮

void highlight(u16 Linex, uint8_t *str, uint8_t pos)
{
	int i = 0;
	for(i = 0; i <= 19; i++)
	{
		if(i != pos)
			LCD_DisplayChar(Linex, (320 - (16 * i)), str[i]);
	}
	LCD_SetBackColor(Yellow);
	LCD_DisplayChar(Linex, (320 - (16 * pos)), str[pos]);
	LCD_SetBackColor(Blue);	
}
使用
//LCD_Disp
sprintf((char*)Buf,"  Threshold 1: %02ucm  ", Threshold_Buf[0]);
if(lcd_light == 1)highlight(Line3, Buf, 16);
else LCD_DisplayStringLine(Line3, Buf);
memset(Buf,0,20*sizeof(uint8_t));

多个字节高亮

//自己加参数,想高亮几个就高亮几个。

void highlight(u16 Linex, u8* buf, u16 num1, u16 num2, u16 num3)
{
  int i;
  for (i = 0; i<=19; i++)
  {
    if ((i != num1) && (i != num2) && (i != num3))
    {
      LCD_DisplayChar(Linex, (320 - 16 * i), buf[i]);
    }
  }
  LCD_SetBackColor(Red);
  LCD_DisplayChar(Linex, (320 - 16 * num1), buf[num1]);
  LCD_DisplayChar(Linex, (320 - 16 * num2), buf[num2]);
  LCD_DisplayChar(Linex, (320 - 16 * num3), buf[num3]);
  LCD_SetBackColor(Black);
}
使用
//LCD_Disp
sprintf((char*)Buf,"  Threshold 1: %02ucm  ",Threshold_Buf[0]);
if(lcd_light == 0)highlight(Line3, Buf, 10, 11, 12);
else LCD_DisplayStringLine(Line3, Buf);
memset(Buf,0,20*sizeof(uint8_t));


行闪烁

//原理就是下面LED_Toggle函数那里。

void Lcd_Toggle(u16 Linex, u8 *buf, u16 time, u16 num)
{
    int i;
    for (i = 0; i < num; i++)
    {
        LCD_DisplayStringLine(Linex, buf);
        Delay_Ms(time / num / 2);
        LCD_ClearLine(Linex);
        Delay_Ms(time / num / 2);
    }
}

使用

sprintf((char *) lcd_buf, "TIM3Freq1 = %d  ", TIM3Freq1);
if (lcd_flag == 3)
{
    Lcd_Toggle(Line5, lcd_buf, 2000, 6);
    lcd_flag = 0;
}
else LCD_DisplayStringLine(Line5, lcd_buf);
memset(lcd_buf, 0, 20 * sizeof(u8));
LCD_SetBackColor(Blue);


LED

display函数

void Led_Disp(u16 Ledx,FunctionalState NewState){
	if(NewState == ENABLE){
	  GPIO_ResetBits(GPIOC,Ledx << 8);
	  GPIO_SetBits(GPIOD,GPIO_Pin_2);
	  GPIO_ResetBits(GPIOD,GPIO_Pin_2);
	}
	else{
	  GPIO_SetBits(GPIOC,Ledx << 8);
	  GPIO_SetBits(GPIOD,GPIO_Pin_2);
	  GPIO_ResetBits(GPIOD,GPIO_Pin_2);
	}
}

void Led_Toggle(u16 Ledx){
	GPIO_SetBits(GPIOD,GPIO_Pin_2);
	GPIOC->ODR ^= (Ledx << 8);
	GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}

注意:为了解决与LCD的冲突问题,需要改变lcd.c里的三个函数——

在这里插入图片描述
在这三个函数的开头加上——

u16 pcout = GPIOC->ODR;	// 先把GPIOC的ODR寄存器读取出来

结尾加上——

GPIOC->ODR = pcout;		// 操作完LCD后,再将GPIOC的ODR寄存器原来的值恢复,即不改变LED的状态

记得在LED_Init()函数中关掉所有LED。



Toggle函数——LED闪烁

void Led_Toggle(u16 Ledx){//led.c
	GPIO_SetBits(GPIOD,GPIO_Pin_2);
	GPIOC->ODR ^= (Ledx << 8);
	GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
void Led_Toggle_Disp(u16 Ledx,u16 Toggle_Time_ms,u16 num){//main.c
	//Toggle_Time_ms总时长,如1000ms即1s
	//num 闪烁几次
	//亮灭周期为 Toggle_Time_ms/num/2
	int i = 0;
	for(i = 0;i < 2 * num;i ++){
		Delay_Ms(Toggle_Time_ms/num/2);
		Led_Toggle(Ledx);
	}
}

下次写LED闪烁可以直接用这个。



Time_Base

中断服务函数

void TIM4_IRQHandler(void)
{
	static u16 buzzer_count=0;		//定义为静态变量
	if (TIM_GetITStatus(TIM4,TIM_IT_Update) != RESET)
	{
		TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
		buzzer_count++;
		if(buzzer_count==500)
		{
			buzzer_count = 0;
			buzzer_flag =1;
		}
	}
}

注意: 要检测是否进入中断,以及清零标志位。
改变状态值的相关计数值,最好用static写在中断函数里面。



Buzzer

使能

/**************************************************************************** 
* 函数名: Buzzer_Ctrl() 
* 功 能: 控制蜂鸣器
* 输 入: FunctionalState NewState,判断使能还是失能        
* 输 出: 无 
*/
void Buzzer_Ctrl(FunctionalState NewState)
{
	if (NewState != ENABLE)
	{
		GPIO_SetBits(GPIOB,GPIO_Pin_4);
	}
	else
	{
		GPIO_ResetBits(GPIOB,GPIO_Pin_4);
	}
}

注意: 让蜂鸣器响,是清零;让蜂鸣器安静,是置一。



配置GPIO

蜂鸣器的引脚是接到PB4的,而默认的情况下,PB4的功能是JNTRST,所以我们要把他重映射为GPIO引脚,同时需要注意,还要使能AFIO功能的时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST,ENABLE);

注意:在初始化GPIO的时候一定要细心.

GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST,ENABLE);

注意, 这里是ENABLE;



KEY

变量调用

KEY的相关变量可以定义在.c文件中,然后在.h文件中声明。
然后main.c文件中,只要包含.h文件就能直接使用该变量。



注意宏定义运算表达式

调用时一定要加括号,不然运算顺序可能和你想得不一样。



Scan函数

uint8_t Key_Scan(void)
{
	uint8_t Key_Val = 0;
	if (~GPIO_ReadInputData(GPIOA) & 0x101)
	{
		Delay_Key(10);
		if (!GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_0))
			return 1;
		else if (!GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_8))
			return 2;
	}
	else if (~GPIO_ReadInputData(GPIOB) & 0x06)
	{
		Delay_Key(10);
		if (!GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_1))
			Key_Val = 3;
		else if (!GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_2))
			Key_Val = 4;
	}
	return Key_Val;
}

void Delay_Key(u16 ms)
{
	int i, j;
	for(i = 0; i<ms; i++)
	 for(j = 0; j<7992; j++);//72MHz
}

注意取反延时
注意是 GPIO_ReadInputData;



Disp函数

只考虑短按(单击)

void Key_Disp(void)
{
	static uint8_t Key_Val = 0;
	static uint8_t Key_Down = 0;
	static uint8_t Key_Old = 0;
	
	Key_Val = Key_Scan();
	Key_Down = Key_Val & (Key_Val ^ Key_Old);
	Key_Old = Key_Val;
	
	switch (Key_Down)
	{
		case 1:lcd_count++;break;
		case 2:lcd_count++;break;
		case 3:lcd_count++;break;
		case 4:lcd_count++;break;
	}
	
}

注意:一定要记得加上static,不然会运行多次。


考虑长短按

void Key_Disp(void)
{
	static uint8_t Key_Val = 0;//键值
	static uint8_t Key_Down = 0;//当前键值
	static uint8_t Key_Old = 0;//上一次键值
	static u16 Key1_time = 0;//B1按下时间
	static uint8_t key1_flag = 1;//B1长按标志位
	
	Key_Val = Key_Scan();
	Key_Down = Key_Val & (Key_Val ^ Key_Old);
	Key_Old = Key_Val;
	
	if (Key_Old == 1)//当按下B1
	{
		Key1_time += 10;//开始计数,这个具体时间不清楚,按道理是每次10ms
		if (Key1_time>150 && key1_flag == 1)
		{
			lcd_count += 10;
			Key1_time = 0;
			key1_flag = 0;
		}
	}
	if (Key_Down == 0 && Key_Old == 0)//按键松开
	{
	    //这个短按上限时间最好小于长按判断时间,不然长按完,还会触发一次短按,
	    //同时要注意短按的检测时间,若写0-50,则短按就检测不到了,50-150之间是不会进行操作的
		if (Key1_time>0 && Key1_time<100)
		{
			lcd_count++;
		}
		
		//恢复B1相关标志位
		Key1_time = 0;
		key1_flag = 1;
	}
	
}


E2PROM

参考博客:蓝桥杯嵌入式_STM32 学习_IIC。

掉电不丢失

uint8_t IIC_flag = 0xdd;//标志位的写入数据
uint8_t IIC_Flag = 0;//标志位的读取数据
uint8_t Threshold_Buf[3] = {0};//数据的读取数据
uint8_t IIC_Buf[3] = {30,50,70};//数据的写入数据

//写main.c里
E2PROM_Read_long(&IIC_Flag,0x10,1);
if(IIC_Flag == 0xdd){
	E2PROM_Read_long(Threshold_Buf, 0x00, 3);
}
else{
	E2PROM_Write_long(&IIC_flag, 0x10, 1);
	Delay_Ms(200);
	E2PROM_Write_long(IIC_Buf, 0x00, 3);
	Delay_Ms(200);
	E2PROM_Read_long(Threshold_Buf, 0x00, 3);
}

在别的地址写入一个值作为标志位,每次重启先判断标志位是否是我们写入的值:
如果是,那么就直接读取我们在指定位置写入的数据;如果不是,那我们就写入标志位数据,以及我们自己运行的变量数据。

注意:写入标志位的值要用十六进制,因为一个地址是八位。



写入数据函数

在这里插入图片描述
(图片来源:AT24C02.pdf)

/*******************************************************************************
* 函数名	:E2PROM_Write_long
* 输入值	:unsigned char *pucBuf,unsigned char ucAddr,unsigned char ucNum
* 返回值	:none
* 功能描述:连续写入多个数据
* 备注	:pucBuf为源数据指针,ucAddr为E2PROM中要写入的数据起始地址,ucNum为写入数据的个数。
*******************************************************************************/

void E2PROM_Write_long(unsigned char* pucBuf, unsigned char ucAddr,
  unsigned char ucNum)
{
  I2CStart(); //起始信号
  I2CSendByte(0xa0); //器件地址
  I2CWaitAck(); //等待应答

  I2CSendByte(ucAddr);	//数据地址
  I2CWaitAck();//等待应答

  while(ucNum--)//写入个数
  {
    I2CSendByte(*pucBuf++);//写入数据 
    I2CWaitAck(); //等待应答
  }
  I2CStop();//停止信号
  delay1(500);
}




读取多个数据

在这里插入图片描述
(图片来源:AT24C02.pdf)

/*******************************************************************************
* 函数名	:E2PROM_Read_long
* 输入值	:unsigned char *pucBuf,unsigned char ucAddr,unsigned char ucNum
* 返回值	:none
* 功能描述:连续读取多字节数据
* 备注	:pucBuf为存储数组指针,ucAddr为E2PROM中要读取的数据起始地址,ucNum为读取数据的个数。
*******************************************************************************/

void E2PROM_Read_long(unsigned char* pucBuf, unsigned char ucAddr,
  unsigned char ucNum)
{
  I2CStart(); //起始信号
  I2CSendByte(0xa0);//器件地址 - 写
  I2CWaitAck(); //等待应答

  I2CSendByte(ucAddr);//数据地址
  I2CWaitAck(); //等待应答
	
  I2CStart();//起始信号
  I2CSendByte(0xa1); //器件地址 - 读
  I2CWaitAck();//等待应答

  while(ucNum--)//读取个数
  {
    *pucBuf++ = I2CReceiveByte();//读取数据
    if(ucNum)//判断是否继续读取
      I2CSendAck();//发送有效应答
    else
      I2CSendNotAck();//发送无效应答
  }
  I2CStop();//停止信号
}


多类型读写

EEPROM一个地址,存入一个字节的数据,所以当数据范围小于256时,尽量用uint8_t类型;若大于256,则针对不同类型的数据,需要分离成单个字节的数据。
但分离字节有点麻烦。
所以我们可以用共用体来写——

//利用共用体读写EEPROM
union eeprom_dat
{
	uint8_t t1;
	uint16_t t2;
	uint32_t t3;
	int16_t t4;
	float f1;
	double f2;
	unsigned char str[20];
}eeprom_dat_write,eeprom_dat_read;

//main.c文件中
i2c_init();					//I2C总线初始化

/*字符串读写*/	
strcpy((char *)eeprom_dat_write.str, "Hello World!!!");
E2PROM_Write_long(eeprom_dat_write.str, 0x10, strlen((char *)eeprom_dat_write.str));
Delay_Ms(200);

E2PROM_Read_long(eeprom_dat_read.str, 0x10, strlen((char *)eeprom_dat_write.str));
Delay_Ms(200);

sprintf((char*)lcd_string,"%s      ", eeprom_dat_read.str);
LCD_DisplayStringLine(Line4, (unsigned char *)lcd_string);	

/*浮点型读写*/	
eeprom_dat_write.f2 = 3.1415926535;
E2PROM_Write_long(eeprom_dat_write.str, 0x20, sizeof(eeprom_dat_write.f2));
Delay_Ms(200);

E2PROM_Read_long(eeprom_dat_read.str, 0x20, sizeof(eeprom_dat_write.f2));
Delay_Ms(200);

sprintf((char*)lcd_string,"%f        ",eeprom_dat_read.f2);
LCD_DisplayStringLine(Line5,(unsigned char *)lcd_string);	

注意:字符串用strlen,其他用sizeof
(字符串自带结尾空格,strlen计数不加空格,sizeof计数加空格)
注意加上强制转换。
记得共用体是分号。



注意

(1) 自己完成读写EEPROM的函数,I2C驱动比赛提供;
(2) 两次数据写入间隔为:5ms;
(3) 赛题指定初值时:在程序初始化时预先写入数值,再屏蔽掉该函数;
(4) 不要在while(1)频繁读写EEPROM,AT24C02写的寿命为100w次。如果5ms写入一次,500分钟就把EEPROM写坏了。
(参考:电子设计工坊)

注意:
写地址是0xa0,读地址是0xa1;
初始化函数别忘写了!
起始函数该写的地方都加上!!!
一定要记得在main函数里调用初始化函数!!!!



RTC

快速配置

在比赛提供的 V3.5 库的 “Project->STM32F10x_StdPeriph_Examples->RTC->LSI_Calib” 文件夹下,打开 “main.c”:
在这里插入图片描述
直接复制粘贴 RTC_Configuration () 部分,去掉最后两句代码,加上我们的计数值设定即可。
RTC_SetCounter () 和 RTC_GetCounter () 可以在库函数文件 “stm32f10x_rtc.h” 里找到。
记得加上中断设置。

u32 Time=23*3600+50*60+10;//写为rtc.c里的全局变量
/*Init函数内容*/
  NVIC_InitTypeDef NVIC_InitStructure;

  //使能RTC中断
  NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; 
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  //加上这一句就行,设置初始时间
  //RTC_SetCounter(3600 * HH + 60 * MM + SS); 
  RTC_SetCounter(Time);

注意:u32 Time要是u32类型的,u16会出错。

在相同目录下,打开 “stm32f10x_it.c” 还可以看到 RTC 中断函数相关代码,修改修改直接使用即可:
在这里插入图片描述

void RTC_IRQHandler(void)
{
  if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
  {
		RTC_Time = RTC_GetCounter();
		if (RTC_Time == 86400)//到24点清零
		{
			RTC_Time = 0;//当前秒的值
			RTC_SetCounter(1);//下一秒的值
			RTC_WaitForLastTask();//这个一定要加,不然会出错
		}

    /* Clear Interrupt pending bit */
    RTC_ClearITPendingBit(RTC_FLAG_SEC);
  }
}

//main.c函数调用

#include "rtc.h"

void window()
{
    u8 str[20];
    Time = RTC_GetCounter();
    sprintf(str1,"%0.2d-%0.2d-%0.2d",Time/3600,(Time%3600)/60,(Time%3600)%60);
	LCD_DisplayStringLine(Line2, str);
}

int main()
{
    ...
    rtc_Init();
    while(1)
    {
        window();
        delay_ms(300);
    }
}



ADC

注意的点

1、GPIO管脚是PB0,通道8;
2、分频系数是6:RCC_PCLK2_Div6
3、sprintf((char*)lcd_buf, "ADC_val : %.2f ", ADC_val/4095.0f*3.3f);

if (ADC_flag)
	{
		ADC_flag = 0;
		ADC_val = ADC_GetConversionValue(ADC1);//这个函数在ADC库函数里
	}


PWM

定时器通道引脚分布图表

在这里插入图片描述



输出两路频率固定占空比可调的 PWM----文件名:PWM_Output

快速配置

在比赛提供的 V3.5 库的 “Project->STM32F10x_StdPeriph_Examples->TIM->PWM_Output” 文件夹下,打开 “main.c”:
(注意,不是7PWM_Output)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上面的根据自己的需求修改就行。


设置占空比

void PWM1_ctrl(u16 cycle, u16 ch2_duty, u16 ch3_duty)
{
    TIM_SetAutoreload(TIM2, cycle);//周期@1us
	TIM_SetCompare2(TIM2,ch2_duty / 100.0f * fq);//占空比
	TIM_SetCompare3(TIM2,ch3_duty / 100.0f * fq);//占空比
}

周期与频率换算方法:
设置定时器为72分频,则计数一次为us.
周期与频率互为倒数,将已知频率求倒数再乘上10的六次方us,即一秒,即可得到周期。


使用方法

#include "pwm_1.h"
//main.c里——
PWM1_Init();
PWM1_ctrl(1000, 30, 60);//周期都为1000us,即频率都为1000Hz,占空比一个30%,一个60%


输出两路频率可调占空比可调的 PWM----文件名:OCToggle

快速配置

在比赛提供的 V3.5 库的 “Project->STM32F10x_StdPeriph_Examples->TIM->OCToggle” 文件夹下,打开 “main.c”:
在这里插入图片描述

在这里插入图片描述
预分频值设置为71.
在这里插入图片描述
在这里插入图片描述
基本上比较输出的设置代码都在这里,更改相应的引脚和通道就可以。

再打开同目录下的 “stm32f10x_it.h”:

在这里插入图片描述
在这里插入图片描述
这里中断服务函数已经有了输出相应频率的代码,
我们对中断服务函数进行扩充增加占空比部分即可——

uint16_t capture = 0;
u8 pa6_state=0,pa7_state=0;
void TIM3_IRQHandler(void)
{
  /* TIM3_CH1 toggling with frequency = 183.1 Hz */
  if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
  {
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC1 );
    capture = TIM_GetCapture1(TIM3);
		if (pa6_state==0)
		{
			TIM_SetCompare1(TIM3, capture + (u16)CCR1_Val * duty1 );
			pa6_state = 1;
		}		
		else
		{
			TIM_SetCompare1(TIM3, capture + (u16)CCR1_Val * (1 - duty1) );
			pa6_state = 0;
		}
    
  }

  /* TIM3_CH2 toggling with frequency = 366.2 Hz */
  if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
  {
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
    capture = TIM_GetCapture2(TIM3);
		if (pa7_state==0)
		{
			TIM_SetCompare2(TIM3, capture + (u16)CCR2_Val * duty2 );
			pa7_state = 1;
		}		
		else
		{
			TIM_SetCompare2(TIM3, capture + (u16)CCR2_Val * (1 - duty2) );
			pa7_state = 0;
		}
  }
}


使用方法

CCR1_Val是周期;
duty1是占空比,设置时记得为float类型的小数
pa6_state是为了产生方波;
所有变量都定义在PWM.c文件里即可,需要改变的值如CCR1_Valduty1在头文件用extern声明就行,然后用按键什么的改变这些参数即可。

注意:

PA6是CH1通道,写代码要与CCR1_ValTIM_OC1Init()TIM_OC1PreloadConfig()TIM_IT_CC1TIM_GetCapture1()TIM_SetCompare1()对应,不要CH1用到了CH2的参数或者库函数。

当发现波形不是你想要的答案时,除了参数的数据设置要注意,这个参数与库函数的对应关系也要注意。



捕获一路PWM的频率和占空比----文件名:PWM_Input

快速配置

在比赛提供的 V3.5 库的 “Project\STM32F10x_StdPeriph_Examples\TIM*PWM_Input* 文件夹下,打开 “main.c”:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
基本上比较输出的设置代码都在这里,更改相应的引脚和通道就可以。
再打开同目录下的"stm32f10x_it.h”:
在这里插入图片描述
在这里插入图片描述

使用方法

IC2Value是比较值;//别问什么是比较值,我也不知道,只是应该是这个意思。。。
DutyCycle是占空比,直接是u16类型的;
Frequency是频率;
所有变量都定义在pwm_ic.c文件里即可,需要获取的值如DutyCycleFrequency在头文件用extern声明就行,然后用LCD显示即可。

注意:

1、注意通道一致,不要CH1用到了CH2的参数或者库函数;
2、中断服务函数中,两个画线的地方需要注意,获取的频率是用设置的通道相对应的库函数,比较值是用另一个通道的库函数,两者必须不同,否则不能实现占空比和频率的获取。

捕获两路PWM的频率和占空比

思路

直接用上面捕获一路的代码复制两遍,然后用滴答定时器中设置一个flag来实现不同时间段分别采样,这样就不会有冲突。

代码

//pwm_ic.c

#include "pwm_ic.h"
void PWM_IC_Init_6(void)
{
    TIM_ICInitTypeDef  TIM_ICInitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* Enable the TIM3 global Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* TIM3 channel 2 pin (PA.07) configuration */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    /* GPIOA clock enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICFilter = 0x0;

    TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);

    TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);

    /* Select the slave Mode: Reset Mode */
    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);

    /* Enable the Master/Slave Mode */
    TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);

    /* TIM enable counter */
    TIM_Cmd(TIM3, ENABLE);

    /* Enable the CC2 Interrupt Request */
    TIM_ITConfig(TIM3,TIM_IT_CC1, ENABLE);
}

void PWM_IC_Init_7(void)
{
    TIM_ICInitTypeDef  TIM_ICInitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* Enable the TIM3 global Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* TIM3 channel 2 pin (PA.07) configuration */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    /* GPIOA clock enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICFilter = 0x0;

    TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);

    TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2);

    /* Select the slave Mode: Reset Mode */
    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);

    /* Enable the Master/Slave Mode */
    TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);

    /* TIM enable counter */
    TIM_Cmd(TIM3, ENABLE);

    /* Enable the CC2 Interrupt Request */
    TIM_ITConfig(TIM3,TIM_IT_CC2, ENABLE);
}

__IO uint16_t IC2Value1 = 0;
__IO uint16_t DutyCycle1 = 0;
__IO uint32_t Frequency1 = 0;

__IO uint16_t IC2Value2 = 0;
__IO uint16_t DutyCycle2 = 0;
__IO uint32_t Frequency2 = 0;

void TIM3_IRQHandler(void)
{
    /* Clear TIM3 Capture compare interrupt pending bit */
    if (TIM_GetITStatus(TIM3, TIM_IT_CC2))
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);

        /* Get the Input Capture value */
        IC2Value2 = TIM_GetCapture2(TIM3);

        if (IC2Value2 != 0)
        {
            /* Duty cycle computation */
            DutyCycle2 = (TIM_GetCapture1(TIM3) * 100) / IC2Value2;

            /* Frequency computation */
            Frequency2 = SystemCoreClock / IC2Value2;
        }
        else
        {
            DutyCycle2 = 0;
            Frequency2 = 0;
        }
    }

    /* Clear TIM3 Capture compare interrupt pending bit */
    if (TIM_GetITStatus(TIM3, TIM_IT_CC1))
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);

        /* Get the Input Capture value */
        IC2Value1 = TIM_GetCapture1(TIM3);

        if (IC2Value1 != 0)
        {
            /* Duty cycle computation */
            DutyCycle1 = (TIM_GetCapture2(TIM3) * 100) / IC2Value1;

            /* Frequency computation */
            Frequency1 = SystemCoreClock / IC2Value1;
        }
        else
        {
            DutyCycle1 = 0;
            Frequency1 = 0;
        }
    }

}

//main.c

if (PWM_IC_flag)
{
    PWM_IC_Init_6();
    TIM_ITConfig(TIM3, TIM_IT_CC2, DISABLE);
}
else
{
    PWM_IC_Init_7();
    TIM_ITConfig(TIM3, TIM_IT_CC1, DISABLE);
}

//stm32f10x.it.c

extern u8 PWM_IC_flag;
void SysTick_Handler(void)
{
    static __IO u32 t = 0;
    TimingDelay--;
    if (t ++ == 100)
    {
        PWM_IC_flag ^= 1;
        t = 0;
    }
}


串口与TIM2冲突问题

#define PWM_ENABLE 	1
#define UART_ENABLE 2
void PWM_UART_Enable(u8 flag)
{
	if(flag==PWM_ENABLE)
	{
		USART_Cmd(USART2, DISABLE);
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, DISABLE);
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);	
		TIM_Cmd(TIM2, ENABLE);
	}
	
	if(flag==UART_ENABLE)
	{
		TIM_Cmd(TIM2, DISABLE);
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, DISABLE);		
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
		USART_Cmd(USART2, ENABLE);
	}
}

串口

基本知识

管脚: GPIOA2、GPIOA3; PA2是复用推挽输出,PA3是浮空输入

时钟: USART2是APB1总线;记得开复用时钟;

使用

// 发送字符
unsigned char USART_SendChar(USART_TypeDef* USARTx, unsigned char ucChar)
{
  USART_SendData(USARTx, ucChar);
  while(!USART_GetFlagStatus(USARTx, USART_FLAG_TXE));//USART_FLAG_TC 表示传输完毕;USART_FLAG_TXE表示发送缓冲区空
  return ucChar;
}
// 发送字符串
void USART_SendString(USART_TypeDef* USARTx, unsigned char* pucStr)
{
  while(*pucStr != '\0')
    USART_SendChar(USARTx, *pucStr++);
}
void USART2_IRQHandler(void){
	if(USART_GetITStatus(USART2,USART_IT_RXNE)){
		RxOver = 1;
		Uart_Buf = USART_ReceiveData(USART2);
		USART_ClearITPendingBit(USART2,USART_IT_RXNE);
	}
}

闲时判断

在串口中断服务函数加上一个时间标志位,当触发串口中断就将其清零。
在定时器里用此标志位计数,当增加到一定数量时,清空串口缓冲数组。

void USART2_IRQHandler(void)
{
	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
	{
	    //使用函数内容
		rx_ideltime=0;//一个时间标志位
	}
}

//定时器闲时判断
void TIM4_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM4,TIM_IT_Update) != RESET)
	{
		TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
		rx_ideltime++; 
		if(rx_ideltime>=50)
		{
			rx_ideltime=0;
			rx_count=0;
			memset(rx_buf,0,15);
		}
	}
}

善用状态

用一个标志来作为状态切换触发;
例如,输入一个ABCD-1234-A2C4
那么,可以将’-'作为状态切换的契机,每四位数据作为一组状态——

extern uint8_t RxOver;
extern uint8_t Uart_Buf[5];
extern uint8_t Uart_flag1[5];
extern uint8_t Uart_flag2[5];
extern uint8_t Uart_flag3[5];
void USART2_IRQHandler(void){
	static uint8_t temp;
	static uint8_t t = 0;
	static uint8_t k_state = 0;
	if(USART_GetITStatus(USART2,USART_IT_RXNE)){
		RxOver = 1;
		temp = USART_ReceiveData(USART2);
		if (temp != '-')
		{
			switch (k_state)
			{
				case 0:Uart_Buf[t] = temp;break;
				
				case 1:
				{
					if(strcmp((char*)Uart_Buf,(char*)Uart_flag1) != 0)
						k_state = 0;
				}break;
				
			    case 2:
				{
					if(strcmp((char*)Uart_Buf,(char*)Uart_flag2) != 0)
						k_state = 0;
				}break;
				
				case 3:
				{
					strcpy(目标数组,(char*)Uart_Buf);
					RxOver = 1;
					k_state = 0;
				}break;
			}
			if(++t == 4){t = 0;k_state++;}
		}
		USART_ClearITPendingBit(USART2,USART_IT_RXNE);
	}
}

当三个标志都需要存储,可以用一个一维数组来当缓冲区,每次判断正确都存入缓冲区,当全部都符合标准,则将缓冲区内的数据存入目标数组。
若有一次不符合,则清零状态,同时清空缓冲区。

C语言知识点

字符与字符串

字符之间判断可以直接写——

if(num_buf[0] != '@')num_buf[0] ++;

字符串直接必须用相对应的函数才行——

strcpy 复制

char*strcpy(char *dest, const char *src)
后者拷贝给前者,结尾空格也会拷贝,要注意分配空间。

strcmp 比较

int strcmp(const char *s1, const char *s2);
strcmp比较两个字符串的大小,一个字符一个字符比较,按ASCII码比较
标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字;
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字。

注意,比较双方的数组都要留一个空格位才行,不然会出错。
如——

uint8_t str1[4] = {'1', '2', '3'};
uint8_t str2[4] = {'1', '2', '3'};
uint8_t str3[4] = {'4', '2', '3'};

strcmp((char*)str1, (char*)str2);
strcmp((char*)str1, (char*)str3);

strlen 取长度(不包括结尾’\0’)

size_t strlen(const char *str)
注意size_t 是无符号整形。

strcat 追加拷贝

char *strcat(char *dest,char *src)
将后面的字符串加到前面的字符串的最后。

注意

这些函数的参数都是char*类型的,要使用强制转换。

提取字符串

// 从字符串中提取车辆信息 
void get_car_info(char *str, pCar_t pcar)
{
	int i = 0, count = 0;
	//提取车辆类型 
	for(i = 0; i < 4; i++, count++) 
		pcar->type[i] = str[count];
		
	//提取车辆ID
	count++;
	for(i = 0; i < 4; i++, count++) 
		pcar->id[i] = str[count];
	
	//取车辆录入时间 	
	count++;
	for(i = 0; i < 12; i++, count++) 
		pcar->time[i] = str[count];
	/*
	printf("pCar_t->type = %s\r\n", pcar->type);
	printf("pCar_t->id = %s\r\n", pcar->id);
	printf("pCar_t->time = %s\r\n", pcar->time);
	*/
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

蓝桥杯嵌入式比赛知识点合集(现在什么都有好吧) 的相关文章

  • windows提权总结

    windows提权总结 内核溢出提权Windows系统配置错误提权系统服务权限配置错误注册表键AlwaysInstallElevated可信任服务路径漏洞自动安装配置文件计划任务 Windows组策略首选项提权 SYSVOL GPP SYS
  • 运行Intel realsense L515相机

    运行Intel realsense L515相机 首先去官 https www intelrealsense com sdk 2 xff0c 按照上面的提示安装各种文件 xff0c 然后输入realsense viewer出现可视化窗口 下
  • python的shellcode_loader解释

    python的shellcode loader解释 代码 loader传到主机执行 xff0c shellcode传到自己的服务器上 简单的python shellcode加载器 xff0c 直接上代码 xff0c 注释都在代码里 代码 s
  • 「网络工程师必会技能」-路由器介绍和路由器基本配置

    网络工程师必会技能 路由器介绍和路由器基本配置 xff0c 这是每个网络必须会的技能 xff0c 不是你有证书就一个网络工程师了哦 xff01 以Cisco路由器为例说明 xff1a xff08 1 xff09 访问路由器 访问路由器与访问
  • 英飞凌微控制器,驱动物联网的关键“大脑”

    英飞凌微控制器 xff0c 驱动物联网的关键 大脑 英飞凌各种各样的传感器以及基于它们的创新应用 xff0c 可谓是打开了传感器的 兵器库 xff0c 令人大开眼界 今天 xff0c 我们将进入 计算 这一环节 xff0c 看看唯样商城代理
  • EMC对策产品:TDK扩大了内置ESD保护功能的陷波滤波器阵容

    EMC对策产品 xff1a TDK扩大了内置ESD保护功能的陷波滤波器阵容 新的陷波滤波器同时实现了ESD保护和最大频率为5 3 GHz频段噪声抑制抑制无线通信中产生的TDMA噪声 xff0c 提高无线信号接收灵敏度强大的静电保护能力 xf
  • 这27个电源符号,别再分不清 快收藏起来学习

    这27个电源符号 xff0c 别再分不清 xff01 快收藏起来学习 以下的V代表Volatge的意思 电源符号 解析 VCC C可以理解为三极管的集电极Collector或者电路Circuit xff0c 指电源正极 VDD D可以理解为
  • 74ls160引脚图引脚图和功能真值表

    74ls160引脚图管脚图及功能真值表 xff0c 74ls160引脚图管脚图74LS160的功能真值表 综合电路图 74ls160引脚图管脚图 74LS160的功能真值表 唯样商城是本土元器件目录分销商 xff0c 采用 小批量 现货 样
  • 最全74HC04六反相器中文资料|引脚图及功能表|应用电路图

    最全74HC04六反相器中文资料 引脚图及功能表 应用电路图 最全74HC04六反相器中文资料 引脚图及功能表 应用电路图 xff0c 该74HC04 74HCT04是高速CMOS器件 xff0c 低功耗肖特基的TTL LSTTL 电路 功
  • 房卡一插就有电 酒店插卡取电原理解析

    房卡一插就有电 酒店插卡取电原理解析 酒店插卡取电的原理是什么 xff0c 入住酒店只需用房卡一插就有电 xff0c 原理是什么呢 xff1f 只是一张塑料片不能导电的啊 导读 xff1a 酒店插卡取电的原理是什么 xff0c 入住酒店只需
  • SiC MOSFET驱动电压的分析及探讨

    SiC设计干货分享 xff08 一 xff09 xff1a SiC MOSFET驱动电压的分析及探讨 随着制备技术的进步 xff0c 在需求的不断拉动下 xff0c 碳化硅 xff08 SiC xff09 器件与模块的成本逐年降低 相关产品
  • EM-500储能网关的AI采集性能实测

    EM 500储能网关的AI采集性能实测 EM 500是致远电子面向工商储能应用推出的高性价比储能网关产品 为满足采集外部传感器数据需要 xff0c EM 500设计内置了多通道高性能AI采集接口 xff0c 本文将对其进行一次实测 EM 5
  • 【IoT开发】UART通信高频测试

    测试所使用芯片 STM32F103RCT6 UART收发的极限频率 xff1a bytes s 1 发送频率 主程序循环发送一字节u8整型 xff0c 记录次数 while 1 t 43 43 if t 61 61 255 t 61 0 p
  • 560V输入、无光隔离反激式转换器

    560V输入 无光隔离反激式转换器 在传统的隔离式高压反激式转换器中 xff0c 使用光耦合器将稳压信息从副边基准电压源电路传输到初级侧 xff0c 从而实现严格的稳压 问题在于 xff0c 光耦合器大大增加了隔离设计的复杂性 xff1a
  • 用于DC-DC转换器的MIL-SPEC COTS EMC输入滤波器

    用于DC DC转换器的MIL SPEC COTS EMC输入滤波器 DC DC转换器的开关动作可能会引起不良的共模和差模噪声 xff0c 在频谱的许多点上创建不可接受的干扰 前端 xff08 或电力线 xff09 滤波器旨在在DC DC转换
  • C语言中调用nop();解决办法

    C语言中调用 nop 解决办法 可在头文件中添加 include lt intrins h gt 或是直接删去 nop intrins h一般用在keilC51单片机编程中 xff0c 一般程序中需要使用到空指令 nop 字符循环移位指令
  • rosrun teleop_twist_keyboard teleop_twist_keyboard.py

    rospack Error package teleop twist keyboard not found 解决方案 xff1a 1 cd catkin ws src xff08 如果没有这个目录先在工作目录下创建工作空间 xff1a mk
  • ubuntu20.04安装ros配置秘钥时出现gpg: keyserver receive failed: Connection timed out

    gpg keyserver receive failed Connection timed out也是从公钥服务器接收失败 xff1a 连接超时 解决方案1 换自己的手机热点 解决方案2 切换网络配置 xff1a 这大多数是网络的问题 xf
  • rosbag的命令使用以及代码编写

    概念 xff1a rosbag是用于录制和回放 ROS 主题的一个工具集 作用 实现了数据的复用 xff0c 方便调试 测试 本质 xff1a rosbag本质也是ros的节点 xff0c 当录制时 xff0c rosbag是一个订阅节点
  • 格式化串漏洞

    格式化字符串漏洞本身并不算缓冲区溢出漏洞 xff0c 这里作为比较典型的一类漏洞进行简单介绍 为了能够将字符串 变量 地址等数据按照指定格式输出 xff0c 通常使用包含格式化控制符的常量字符串作为格式化串 xff0c 然后指定用相应变量来

随机推荐

  • 单链表的遍历

    1 什么是遍历 遍历就是把单链表的各个节点挨个拿出来 xff0c 一个不能少 xff0c 也不能重复 xff0c 追求效率 2 如何遍历单链表 xff08 1 xff09 分析数据结构的本身特点 xff0c 然后根据根据它本身的特点制定相应
  • 单链表之删除节点

    1 删除节点的步骤 xff08 1 xff09 找到要删除的这个节点 xff1a 通过遍历来查找节点 xff0c 从头指针 43 头节点开始 xff0c 顺着链表依次将各个节点拿出来 xff0c 按照一定的方法比对 xff0c 找到我们要删
  • lssek函数的用法及作用

    1 lseek函数的介绍 xff08 1 xff09 文件指针 xff1a 当我们对一个文件读写时 xff0c 一定需要打开这个文件 xff0c 所以我们操作的都是动态文件 xff0c 动态文件在内存中的形态就是流的形式 xff08 2 x
  • ubuntu20.04安装arduino IDE(亲测可用)

    步骤一 xff1a 在官网下载arduino安装包选择相应的版本 下载链接 步骤二 xff1a 解压下载的安装包在相应的目录下执行下面语句 tar xvf 安装包名 步骤三 xff1a 将解压后的安装包移动到 opt目录下 sudo mv
  • px4无人机常识介绍(固件,px4等)

    专业名词解释 aircraft 任何可以飞或者可以携带物品还是搭载旅客的飞行器统称为飞机 航空器 uav 无人驾驶飞机 vehicle 飞行器 airplane plane aero plane 有机翼和一个或多个引擎的飞行器统称为飞机 D
  • 在运行ros的Python文件时报找不到路径

    1 第一行解释器声明 xff0c 可以使用绝对路径定位到 python3 的安装路径 usr bin python3 xff0c 但是不建议 2 建议使用 usr bin env python 但是会抛出异常 usr bin env pyt
  • ros文件架构

    WorkSpace span class token operator span span class token operator span 自定义的工作空间 span class token operator span span cla
  • 用C语言和汇编给寄存器赋值

    1 用汇编 要根据目标CPU的体系 xff0c 用对应的汇编类型编写 ldr r0 61 0X020C4068 CCGR0 ldr r1 61 0XFFFFFFFF str r1 r0 2 用C语言 要知道相关寄存器地址 官方会提供参考手册
  • 商人过河--广度优先搜索--matlab实现

    进行了代码优化 目录 应用背景 xff1a 模型求解 xff1a 模型建立 xff1a 模型实现 xff1a 源代码 xff1a 运行结果 xff1a 附 xff1a 应用背景 xff1a M个商人与N个仆从过河 xff0c 小船一次可载k
  • C++---全局对象、局部对象、静态对象

    1 全局对象 xff0c 程序一开始 xff0c 其构造函数就先被执行 xff08 比程序进入点更早 xff09 xff1b 程序即将结束前其析构函数将被执行 2 局部对象 xff0c 当对象生成时 xff0c 其构造函数被执行 xff1b
  • 2011年B题交通巡警第一问的练习与实现

    题目要求 xff1a 试就某市设置交巡警服务平台的相关情况 xff0c 建立数学模型分析研究下面的问题 xff1a xff08 1 xff09 附件1中的附图1给出了该市中心城区A的交通网络和现有的20个交巡警服务平台的设置情况示意图 xf
  • 利用最大流最小割算法matlab割图

    目录 练习思路 matlab绘图 噪音 坐标编码 邻接矩阵 最大流最小割算法 对最大流最小割算法求解结果转换为图像 源代码 运行实例 TIPS 最近学习了最大流和最小割算法 xff0c 可以把图看成是一些点的集合 xff0c 色彩差值的倒数
  • 关于将一个数分解成四个数平方和的算法matlab

    目录 理论基础 拉格朗日四平方数和定理 高斯恒等式 操作步骤 分解质因数 求解四平方数 应用高斯恒等式 小结 高斯恒等式输出代码 输出结果 运行结果 怎么把一个大数分解成四个小数的平方和呢 xff1f 理论基础 拉格朗日四平方数和定理 每个
  • 寻找较大素数,简易实现RSA密码系统matlab

    目录 RSA密码系统 随机寻找两个较大的素数 欧拉筛的算法函数 寻找随机素数的代码 生成公钥和私钥 加密解密方式 实现代码 运行结果 小结 首先来了解一下什么是RSA算法 RSA密码系统 RSA是被研究得最广泛的公钥算法 xff0c 从提出
  • 关于返回一个矩阵中为0元素个数及位置的matlab自定义函数实现以及用到的matlab基本操作

    目录 练习例题 题目要求 代码呈现 运行结果 基础操作 返回矩阵的行数列数 生成矩阵函数 取整取余函数 自定义函数参数缺省下的默认值以及输入参数为空集下替换为默认值的情况 find函数大观 对于find函数的改善调用 练习例题 题目要求 编
  • 蓝桥杯——单片机学习(3——点亮LED灯)

    注 xff1a 此单片机型号为 STC15F2K60S2 原理 如图 xff0c 发光二极管L1 L8 共阳接法 xff0c VCC为电源正极 xff0c 高电平 已知发光二极管正向导通反向截至 xff0c 要使得二极管发光 xff0c 就
  • 蓝桥杯——单片机学习(5(1)——按键(独立按键))

    注 xff1a 此单片机型号为 STC15F2K60S2 目录标题 独立按键原理按键原理消抖 代码入门代码进阶代码消抖改进 xff08 按一下只执行一次 xff0c 长按也一样 xff09 补充 独立按键 原理 这是一个矩阵按键的电路图 x
  • 最全的蓝桥杯嵌入式备赛集合~

    机缘巧合 xff0c 报了嵌入式的比赛 xff08 我能说是老师逼我的吗 orz xff09 xff0c 由于从来没接触过 xff0c 所以还是先从查找资料开始 下面就是我查找的资料集合 博客 建议篇 64 summerrrrrrc 蓝桥杯
  • 关于STM32编译报错:Error: L6218E: Undefined symbol SystemInit (referred from startup_stm32f10x_md.o).

    今天新建工程发现出现一个错误 Output CG axf Error L6218E Undefined symbol SystemInit referred from startup stm32f10x md o 但我觉得我的操作没有任何问
  • 蓝桥杯嵌入式比赛知识点合集(现在什么都有好吧)

    目录 新建工程LCDsprintf格式输出百分号 输出格式 xff1a Rmemset函数LCD DisplayStringLine函数嘀嗒定时器高亮行高亮一两个字符高亮单个字节高亮使用 多个字节高亮使用 行闪烁使用 LEDdisplay函