蓝桥杯嵌入式模块代码

如何下载keil V5编译器

一、LED

1.基本点亮

void LED_Disp(unsigned char dsled)
{
    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOC,dsled<<8,GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}

2.闪烁灯

void LED_Pro()
{
	if(uwTick-uwTick_LED<100) return;      //用systick实现100ms执行一次函数
	uwTick_LED=uwTick;

    static unsigned char dsled;

    dsled|=0x01;                           //点亮LED1

    dsled&=~0x02;                          //熄灭LED2
	
    dsled^=0x04;                           //用逻辑异或来进行取反操作实现LED3的闪烁
	
	LED_Disp(dsled);
}

3.流水灯

void LED_Pro2()
{
	if(uwTick-uwTick_LED1<100) return;      
	uwTick_LED1=uwTick;
	
	static unsigned char dsled,i;
	dsled|=(0x01<<i);                        //用逻辑左移<<实现移位操作
	i=(i+1)%8;                               //每八次一个循环
	LED_Disp(dsled);
	dsled=0x00;                              //熄灭之前点亮的灯
}

二、LCD

1.初始化

void LCDInit()
{
	LCD_Init();
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
}

2.屏幕显示

u8 page=0;
char LineString[30];

void LCD_Pro()
{
	switch(page)
	{
		case 0:{
			sprintf(LineString,"    Hello World!    ");
			LCD_DisplayStringLine(Line5,(u8 *)LineString);
			break;
		}
//----------------------------//普通显示

		case 1:{
			LCD_SetBackColor(Blue);
			sprintf(LineString,"    Hello World!    ");
			LCD_DisplayStringLine(Line5,(u8 *)LineString);
			
			LCD_SetBackColor(Black);
			sprintf(LineString,"    ni hao!    ");
			LCD_DisplayStringLine(Line6,(u8 *)LineString);
			break;
		}
//----------------------------//让某一行高亮显示
	}
}

有时候可能会让某一行的某一个字符高亮显示:

    LCD_DisplayChar(Line4,320-16*5,'H');
	LCD_DisplayChar(Line4,320-16*6,'e');
	LCD_SetBackColor(Blue);
	LCD_DisplayChar(Line4,320-16*7,'l');
	LCD_DisplayChar(Line4,320-16*8,'l');
	LCD_SetBackColor(Black);
	LCD_DisplayChar(Line4,320-16*9,'o');


/**
  如果需要高亮一行中的某些字符,需要用到LCD_DisplayChar()
  第一个变量为行,第二个变量为列,所用LCD屏一共20列,一列占320/16=20
  最左边是320,所以第i列为320-16*i
  第三个变量为ASCII码字符
**/

补充:使用自定义字符显示

/* '!' */
u16 string[24]={0x0000, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180,
                0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0000, 0x0000,
                0x0180, 0x0180, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}

/*这块LCD屏幕一个小格子的大小为24*16(高*宽)*/


LCD_DrawChar(Line5,320-16*i,string);
 

LCD不同方向显示(文章参考

//--------------正向显示------------------//
LCD_WriteReg(R1  , 0x0000); //从上往下
LCD_WriteReg(R96 , 0x2700); //从左往右
//--------------左右翻转-----------------//
LCD_WriteReg(R1  , 0x0000);  //从上往下
LCD_WriteReg(R96 , 0xA700); //从右往左
//--------------------------------------//
LCD_WriteReg(R1  , 0x0100); //从下往上
LCD_WriteReg(R96 , 0x2700); //从左往右
//--------------180°倒向显示-----------------//
LCD_WriteReg(R1  , 0x0100); //从下往上
LCD_WriteReg(R96 , 0xA700); //从右往左

三、ADC

1.ADC单通道

u32 ADCtick=0;
float voltage,voltage_temp=0;

void ADC_Pro()
{
	if(uwTick-ADCtick<100) return;                    //个人认为100ms采集一次比较合适
	ADCtick=uwTick;
	
	HAL_ADC_Start(&hadc2);
	HAL_ADC_PollForConversion(&hadc2,50);
	for(int i=0;i<10;i++)
		voltage_temp+=HAL_ADC_GetValue(&hadc2)*3.3f/4095.0f;
	voltage=voltage_temp/10;                         //采取10个值求平均
	voltage_temp=0;
}

可能有些板子上的ADC值达不到3.3V,在初始化中加入ADC校准:

HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED);

2.ADC多通道

cubemx配置:

先开启13、17的单通道,选择单次转换模式,再选择通道数为2,采样周期选择最大640.5Cycles就行

拓展板上将PA4、PA5分别与AO1、AO2连接

void ADC_Pro()
{
	if(uwTick-ADCtick<100) return;
	ADCtick=uwTick;
	
	HAL_ADC_Start(&hadc2);
    HAL_ADC_PollForConversion(&hadc2,50);             //最好加上
	voltage=HAL_ADC_GetValue(&hadc2)*3.3f/4095.0f;
	
	HAL_ADC_Start(&hadc2);
    HAL_ADC_PollForConversion(&hadc2,50);
	voltage1=HAL_ADC_GetValue(&hadc2)*3.3f/4095.0f;
}

3.ADC按键

cubemx中配置PA5为ADC输入即可

u8 keyflag=0;

unsigned char ADC_Key()
{
	static u8 keyValue,keystate;
	HAL_ADC_Start(&hadc2);
	ADCValue=HAL_ADC_GetValue(&hadc2);
	
	switch(keystate)
	{
		case 0:if(ADCValue<3990) keystate=1;break;           //按键按下
		case 1:{
			if(ADCValue<200) keyValue=1;
			else if(ADCValue<800) keyValue=2;
			else if(ADCValue<1400) keyValue=3;
			else if(ADCValue<2000) keyValue=4;
			else if(ADCValue<2600) keyValue=5;
			else if(ADCValue<3200) keyValue=6;
			else if(ADCValue<3800) keyValue=7;
			else if(ADCValue<3990) keyValue=8;
			keystate=2;
			break;
		}
		case 2:{
			if(ADCValue>3990) {keystate=0;keyflag=1;}       //按键松开
			break;
		}
	}
	return keyValue;
}

四、串口

cubemx配置如下:

 1.串口发送

HAL_UART_Transmit(&huart1,(u8 *)"hello world",strlen("hello world"),0xff);

2.串口接收

char rx_data[30];
u8 rx_point=0;
u8 rx_temp;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart==&huart1)
	{
		rx_data[rx_point++]=rx_temp;
		HAL_UART_Receive_IT(&huart1,&rx_temp,1);
	}
}

void UART_Rx()
{
	if(rx_point)
		{
			if(rx_data[0]=='1')
				HAL_UART_Transmit(&huart1,(u8 *)"hello world",strlen("hello world"),0xff);
			
			memset(rx_data,0,30);
			rx_point=0;
		}
}

main函数中:

HAL_UART_Receive_IT(&huart1,&rx_temp,1);      //初始化时调用一次即可

if(rx_point)
{
    temp=rx_point;
    HAL_Delay(1);
	if(temp==rx_point)
	    UART_Rx();
}

补充:

(1)memset的使用

#include <string.h>


//**可以用于对数组以及结构体快速清零**//


/*
    param1:数组名称
    param2:通常为0,进行清零操作
    param3:数组大小

*/

memset(rx_data,0,30);                            //对数组清零

memset(&car[location],0,sizeof(car[location]));  //对结构体清零

详细的用法可以参考这篇博客

(2)字符串扫入

typedef struct
{
	char type[5];              //定义字符数组大小时比实际字符长度大1,用于存放“\0”结束符
	char label[5];
	char time[13];
}Car_F;


sscanf(rx_data,"%4s:%4s:%12s",car_temp.type,car_temp.label,car_temp.time);

五、RTC

cubemx配置:

 代码:

#include "rtc.h"

RTC_TimeTypeDef H_M_S_Time;
RTC_DateTypeDef Y_M_D_Date;        //分别定义两个结构体

HAL_RTC_GetTime(&hrtc,&H_M_S_Time,RTC_FORMAT_BIN);     //注意格式为BIN
HAL_RTC_GetDate(&hrtc,&Y_M_D_Date,RTC_FORMAT_BIN);

/*这里两个必须都要调用而不能只调用一个*/

sprintf(LineString,"    Time:%2d:%2d:%2d",
        H_M_S_Time.Hours,H_M_S_Time.Minutes,H_M_S_Time.Seconds);
LCD_DisplayStringLine(Line5,(u8 *)LineString);
			
sprintf(LineString,"    Date:%2d:%2d:%2d",
        Y_M_D_Date.Year,Y_M_D_Date.Month,Y_M_D_Date.Date);
LCD_DisplayStringLine(Line4,(u8 *)LineString);

六、EEPROM

#include "i2c_hal.h"

I2CInit();                                 //注意在main函数中调用进行初始化

void I2C_WriteByte(u8 address,u8 data)
{
	I2CStart();
	I2CSendByte(0xA0);                     //0xA0为写指令
	I2CWaitAck();
	I2CSendByte(address);
	I2CWaitAck();
	I2CSendByte(data);
	I2CWaitAck();
	I2CStop();
	HAL_Delay(5);                          //延时5ms防止写入不完全
}

unsigned char I2C_ReadByte(u8 address)
{
	u8 data;
	I2CStart();
	I2CSendByte(0xA0);                     //先用写指令建立与给定地址的连接
	I2CWaitAck();
	I2CSendByte(address);                
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0xA1);                    //再用0xA1读指令读出地址中的数据
	I2CWaitAck();
	data=I2CReceiveByte();
	I2CWaitAck();
	I2CStop();
	return data;
}


/*该24C02的最大地址为0xFF*/

注意:

如果是V6编译器,记得把代码优化给取消掉,不然读出来始终是255

 如果需要赋予初值:

void EEPROM_process(void)
{
	if(EEPROM_read(0x99)!=0xaa)   //随便定义
	{
		EEPROM_write(0x99,0xaa);
		EEPROM_write(0x01,10);    //设定初值
		EEPROM_write(0x02,10);    //设定初值
		EEPROM_write(0x03,10);    //设定初值
		EEPROM_write(0x04,10);    //设定初值
	}
	else
	{
		X_rep=EEPROM_read(0x00);
		Y_rep=EEPROM_read(0x01);
		X_price=EEPROM_read(0x02);
		Y_price=EEPROM_read(0x03);
	}
}

代码来源于https://blog.csdn.net/dijddnd/article/details/129820235

七、按键

1.短按键

u32 Keytick=0;
u8 temp1[4]={1,1,1,1},temp2[4]={1,1,1,1};
u8 key[4]={0};

void Key_Disp()
{
	if(uwTick-Keytick<20) return;               //20ms扫描除按键抖动
	Keytick=uwTick;
	
	for(int i=0;i<4;i++)
	{
		temp2[i]=temp1[i];
		switch(i)
		{
			case 0:temp1[0]=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);break;
			case 1:temp1[1]=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);break;
			case 2:temp1[2]=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);break;
			case 3:temp1[3]=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);break;
		}
		if(temp1[i]==1&&temp2[i]==0)           //读取上升沿
			key[i]=1;
	}
	
}

void Key_Pro()
{
	Key_Disp();
/*-------按键1*---------/
	if(key[0]==1){
		
		key[0]=0;
	}
/*-------按键2*---------/
	if(key[1]==1){
		
		key[1]=0;
	}
/*-------按键3*---------/
	if(key[2]==1){
		
		key[2]=0;
	}
/*-------按键4*---------/
	if(key[3]==1){

		key[3]=0;
	}
}

 2.长按键

u8 key_count[4]={0};
u8 key_long[4]={0};

void Key_Disp()
{
	if(uwTick-Keytick<20) return;
	Keytick=uwTick;
	
	for(int i=0;i<4;i++)
	{
		temp2[i]=temp1[i];
		switch(i)
		{
			case 0:temp1[0]=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);break;
			case 1:temp1[1]=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);break;
			case 2:temp1[2]=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);break;
			case 3:temp1[3]=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);break;
		}
		if(temp1[i]==1&&temp2[i]==0)
			key[i]=1;
	}
	if(temp1[0]==0)
		key_count[0]++;
	else
		key_count[0]=0;
	
	if(key_count[0]>50)            //超过1s为长按键
	{
		key_count[0]=0;
		key_long[0]=1;
	}
}

void Key_Pro()
{
	Key_Disp();
	if(key[0]==1)
	{
		if(key_long[0]==0)
		    //短按键
		else{
			//长按键
			key_long[0]=0;
		}
		key[0]=0;
	}
}

3.双击

if(temp1[0]==1&&temp2[0]==0)
	{
		uwTick_temp2=uwTick_temp1;
		uwTick_temp1=uwTick;
		if(firstClick==0)
			firstClick=1;
		else
		{
			if(uwTick_temp1-uwTick_temp2<200)
			{
				firstClick =0;
				//双击
			}
			else
			{
				//单击
			}
		}
	}
else
{
	if(firstClick==1&&uwTick - uwTick_temp1 > 200)
	{
			    //单击
		firstClick=0;
	}
}

八、数码管

cubemx配置:

代码:

#define SER_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET)
#define SER_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET)

#define RCK_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,GPIO_PIN_SET)
#define RCK_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,GPIO_PIN_RESET)

#define SCK_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET)
#define SCK_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET)

u8 seg_buff[3];
u8 seg_display[]={                       
//   0    1    2    3    4    5    6    7    8    9 
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

void Seg_Disp()
{
	for(int i=0;i<8;i++)
	{
		if(seg_buff[2]&(0x80>>i)) SER_H;      //因为是移位寄存器,所以高位要先行
		else					  SER_L;
		SCK_L;                                //给上升沿进行移位操作
		SCK_H;
	}
	for(int i=0;i<8;i++)
	{
        //此处不要用"==1"来判断
		if(seg_buff[1]&(0x80>>i)) SER_H;
		else					  SER_L;
		SCK_L;
		SCK_H;
	}
	for(int i=0;i<8;i++)
	{
		if(seg_buff[0]&(0x80>>i)) SER_H;
		else					  SER_L;
		SCK_L;
		SCK_H;
	}
	RCK_L;                                    //最终给一个上升沿进行输出
	RCK_H;
}

void Seg_Pro()
{
	seg_buff[2]=seg_display[0];
	seg_buff[1]=seg_display[1];
	seg_buff[0]=seg_display[2];
	Seg_Disp();
}

 注意:1、在拓展版上要将PA1、PA2、PA3分别通过跳线帽接上SER、RCK、SCK

            2、u8 seg_display[]可以用stc-isp得到

九、光敏电阻 

原理: 把RP7(电位器)处得到的电压值与3处的电压值进行比较器输出得到DO.AO则直接进行adc采样再数模转换得到电压。

拓展板上分别将PA3、PA4连接到TRDO、TRAO

void LDR_Pro()
{
	HAL_ADC_Start(&hadc2);
	voltage=HAL_ADC_GetValue(&hadc2)*3.3f/4095.0f;
	sprintf(LineString,"     V:%.1fV   ",voltage);
	LCD_DisplayStringLine(Line7,(u8 *)LineString);
	if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_3)) 
        LCD_DisplayChar(Line8,320-16*8,'1');           //大于阈值显示1
	else
        LCD_DisplayChar(Line8,320-16*8,'0');           //小于阈值显示0
}


/*阈值可由RP7电位器控制*/

 十、DS18B20

拓展板上将PA6与TDQ连接

float ds18b20_read(void)
{
	float temper;
	unsigned char low,high;
	ow_reset();                               //开启信号传输
	ow_byte_wr(OW_SKIP_ROM);                  //跳过ROM(0xCC)
	ow_byte_wr(DS18B20_CONVERT);              //温度转化(0x44)
	
	ow_reset();
	ow_byte_wr(OW_SKIP_ROM);
	ow_byte_wr(DS18B20_READ);                 //温度读取(0xBE)
	low=ow_byte_rd();
	high=ow_byte_rd();
	temper=((high<<8)|low)*0.0625;            //返回16位数据,且精度为0.0625
	
	return temper;
}
/*需要在ds18b20.c中自行编写*/
#include "ds18b20.h"

ds18b20_init_x();                     //ds18b20初始化
while(ds18b20_read()==85);            //防止上电后的一段时间显示默认值85

十一、DHT11

 

 返回数据格式:

        温度整数部分(8位)+温度小数部分(8位)+湿度整数部分(8位)+湿度小数部分(8位)+校验位(8位)

void DHT11_Process()  
{
	if(uwTick - humTick < 500)	return; //500ms读取一次
	humTick = uwTick;
	
	dht11_val = dht11_read();
 
}
 
sprintf((char*)display_buf,"T:%d.%d ",(dht11_val>>8)&0xff,dht11_val&0xff);//温度
LCD_DisplayStringLine(Line6 ,(unsigned char *)display_buf);
sprintf((char*)display_buf,"H:%d ",dht11_val>>24); //湿度
LCD_DisplayStringLine(Line7 ,(unsigned char *)display_buf);

 注意:

DS18B20与DHT11编译时要用V5编译器

十二、PWM

1.单通道测量频率

u16 frq=0;
u32 ccr=0;

HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);           //main函数初始化

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM3)
	{
		ccr=TIM3->CNT;
		TIM3->CNT=0;                                 //一定要将CNT的值置零
		frq=80000000/80/ccr;
		HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
	}
}

 2.测量占空比

(1)双通道

HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);                 //main函数初始化

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM3)
	{
		if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_2)
		{
			ccr1=HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2);
			if(ccr1)
			{
				ccr2=HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);
				TIM3->CNT=0;
				frq=80000000/80/ccr1;
				duty=(ccr2+1)*100/(ccr1+1);
				HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
				HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
			}
		}
	}
}
 (2)单通道

u16 ccr1,ccr2;
float frq;
float duty;

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
  if(htim->Instance==TIM3)
  {
    if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_2)
	{

	 if(tim3_state==0){
	   TIM3->CNT=0;
	   __HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_FALLING);
	   tim3_state=1;
	  }
	  else if(tim3_state==1){
		ccr2=HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2);
		__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_RISING);
		tim3_state=2;
	  }
	  else if(tim3_state==2){
	    ccr1=HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2);
	    frq=80000000.0f/80.0f/(float)(ccr1+1);
		duty=(float)(ccr2+1)/(float)(ccr1+1)*100.0f;
		tim3_state=0;
	  }
		HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
	}
   }
}

(3)测双路PWM占空比

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM3)
	{
		if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)      						//PA6
		{
			if(time_state[0]==0){
				ccr1[0]=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
				__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);
				time_state[0]=1;
			}
			else if(time_state[0]==1){
				ccr2[0]=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
				if(ccr2[0]>ccr1[0])
					ccr_h[0]=ccr2[0]-ccr1[0];
				else
					ccr_h[0]=ccr2[0]+0xFFFF-ccr1[0];
				
				ccr1[0]=ccr2[0];
				__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);
				time_state[0]=2;
			}
			else if(time_state[0]==2){
				ccr2[0]=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);
				if(ccr2[0]>ccr1[0])
					ccr_l[0]=ccr2[0]-ccr1[0];
				else
					ccr_l[0]=ccr2[0]+0xFFFF-ccr1[0];
				duty[0]=(float)(ccr_h[0])/(float)(ccr_h[0]+ccr_l[0])*100.0f;
				time_state[0]=0;
			}
			HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
		}
		else if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_2) 					  //PA7
		{
			if(time_state[1]==0){
				ccr1[1]=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2);
				__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_FALLING);
				time_state[1]=1;
			}
			else if(time_state[1]==1){
				ccr2[1]=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2);
				if(ccr2[1]>ccr1[1])
					ccr_h[1]=ccr2[1]-ccr1[1];
				else
					ccr_h[1]=ccr2[1]+0xFFFF-ccr1[1];
				
				ccr1[1]=ccr2[1];
				__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_2,TIM_INPUTCHANNELPOLARITY_RISING);
				time_state[1]=2;
			}
			else if(time_state[1]==2){
				ccr2[1]=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2);
				if(ccr2[1]>ccr1[1])
					ccr_l[1]=ccr2[1]-ccr1[1];
				else
					ccr_l[1]=ccr2[1]+0xFFFF-ccr1[1];
				duty[1]=(float)(ccr_h[1])/(float)(ccr_h[1]+ccr_l[1])*100.0f;
				time_state[1]=0;
			}
			HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
		}
	}
}

/*
    这里用差值来计算频率以及占空比,不用清零法是因为两个通道会互相影响
*/

小知识

#include "math.h"

float a;
a=fabs(a);     //对浮点数取绝对值
int a=100;
printf("%X",a);    //将a以16进制输出(大写字母)
printf("%x",a);    //将a以16进制输出(小写字母)


printf("%#x",a);    //在16进制数前面加上0x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值