当前位置:主页 > 查看内容

使用HAL库开发蓝桥杯第十届决赛题目---各模块程序(康复训练)

发布时间:2021-04-19 00:00| 位朋友查看

简介:本文章多以图片代替文字方便大家直接在软件上实践。 我们先看题目 先分析题目 一共两个LCD界面外设基本上全部配置II2读写EEPROM同时需要用到串口收发指令 数码管和AO1/AO2引脚都在拓展板上。 看似可能比较难我们一步步往下做。 先打开cubemx按照原理图配置引……

本文章多以图片代替文字,方便大家直接在软件上实践。

我们先看题目
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 先分析题目: 一共两个LCD界面,外设基本上全部配置,II2读写EEPROM,同时需要用到串口收发指令
    数码管和AO1/AO2引脚都在拓展板上。 看似可能比较难,我们一步步往下做。

先打开cubemx按照原理图配置引脚
原理图如下:在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

初始化配置

基本所有引脚都需要配置,为了快速配置 我们直接按照原理图把所有引脚激活
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210401193016758.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NTM2ODI4,size_16,color_FFFFFF,t_70

打开System Core →GPIO 简单的给常用引脚进行一个改名,这里我改了按键的名称和PD2锁存器启用/复位引脚 在这里插入图片描述
在这里插入图片描述

同样是System Core 打开RCC 设置HES为系统时钟源,这里如果不设置,MCU是跑不到最大频率的
在这里插入图片描述
打开顶端 Clock Configuration设置HCLK为170MHZ 回车 ,其他分频器会自动设置
在这里插入图片描述
此时G431的频率就是为最高运行频率了,设置完时钟后,可以开始设置TIM计数器。

再读一遍题:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们一共需要五种不同的定时(注:占空比测量需要独占一个计数器,刷新率可以不管,运行速度够快

这里可以进一步优化 将一个0.2s的定时器做成同时满足1s和2s的,后面程序会讲。
所以,开始设置TIM计数器吧!

首先配置最重要的占空比测量
查询拓展板原理图 PWM2测量引脚为PA7
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210401200405904.png在这里插入图片描述

配置好后 打开左侧列表 Timers 进行TIM3的详细设置
由于只有单引脚输入,所以只能用计数器内部的滤波电路进行一个波形复制,并二次测量波形
在这里插入图片描述

具体设置如下:![在这里插入图片描述](https://img-blog.csdnimg.cn/20210401193402611.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NTM2ODI4,size_16,color_FFFFFF,t_70
TIM3CH2的信号映射到CH1上, CH2下降沿触发,CH1上升沿触发,这样可以做到单引脚的输入捕获

TIM3定时器的分频值我设为频率170 000 000 /预分频值 170-1 /ARR自动复位值 50 000 = 20HZ 也就是最低能测出20*3 =60HZ的方波的频率和占空比
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210401194749672.png
然后打开TIM3的NVIC中断,PWM捕捉肯定需要中断的 ,同时配置TIM1更新中断
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210401194832120.png
占空比测量配置好后,我们继续配置TIM,现在需要配置定时0.2s刷新以及其他用于刷新的定时器
频率170 000 000 /预分频值 17000-1 /ARR自动复位值 2000 = 5HZ =0.2s中断一次
在这里插入图片描述
配置串口并打开中断
在这里插入图片描述
在这里插入图片描述
由于需要收发指令,这里要给串口配置为DMA传输在这里插入图片描述
配置AO1/AO2的ADC测量
在这里插入图片描述
在这里插入图片描述
这里需要打开ADC的循环扫描模式,启用软件触发模式
在这里插入图片描述
设置通道顺序
在这里插入图片描述

此时以及配置完所有引脚了(注:II2C使用的GPIO模拟信号传输数据,不用单独设置II2C。LCD也是GPIO模拟FSMC)
点击在这里插入图片描述
配置工程
在这里插入图片描述
在这里插入图片描述

注意编译器和版本的选择,选择.c和.h文件独立生成文件夹
点击右上角在这里插入图片描述
生成代码
在这里插入图片描述
Open Project自动使用所对应编译器打开工程

打开工程第一步,先编译一次,然后打开stm32g4xx_it.c配置中断函数,删除自带的USART1中断函数,后面需要自己写一个新的,使用空闲中断DMA传输。
新的中断函数自行添加在main.c文件里 要放在BEGIN和END之间,序号随变,如果不在BEGIN和END之间,使用cubemx重新生成文件时会被清空内容。

1.USART:

串口中断编写

void USART1_IRQHandler(void)
{
	if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) != RESET)
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart1);	//清除标记
		HAL_UART_DMAStop(&huart1);	//停止接受 开始处理
		UART_RX_STA = BUFF_SIZE - __HAL_DMA_GET_COUNTER(huart1.hdmarx);
		RXbuf[UART_RX_STA] = 0;
//		UART_RX_STA |= 0X8000;
//		if(UART_RX_STA & 0X8000)
//		{
			if(strcmp((char *)RXbuf,(char *)RX_ST) == 0)		//指令解析
			{
				memset(UARTTEMP,0,30); 
				sprintf(UARTTEMP,"$%.2f\r\n",DS18B20_TEMP);
				HAL_UART_Transmit(&huart1,(uint8_t *)UARTTEMP,sizeof(UARTTEMP),100 );

			}
			else if(strcmp((char *)RXbuf,(char *)RX_PARA) == 0)
			{
				memset(UARTTEMP,0,30); 
				sprintf(UARTTEMP,"#%d,AO%d\r\n",Tmm,Xmm);
				HAL_UART_Transmit(&huart1,(uint8_t *)UARTTEMP,sizeof(UARTTEMP),100);

			}
//			UART_RX_STA = 0;  // 清除标记
//		}
	HAL_UART_Receive_DMA(&huart1, RXbuf, BUFF_SIZE );  // 重新启动DMA接收
	}
}

以下启动函数在main函数内调用

	HAL_UART_Receive_DMA(&huart1,RXbuf,BUFF_SIZE); //打开DMA传输
	__HAL_UART_CLEAR_IDLEFLAG(&huart1);			   //清除中断标记
	__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);	   //打开UART1空闲中断

串口已经配置好了 还有对应的变量需要设置

static char BUFF_SIZE = 50; //接收长度
static uint8_t RXbuf[50];	//接收缓存

static uint16_t UART_RX_STA = 0;     // 第15bit表示一帧数据接收完成,第14~0位表示接收到的数据量
static char UARTTEMP[30];
  1. USART常用函数:
    • HAL_UART_Transmit(&huart*,(uint8_t *)字符数组,sizeof(字符数组),等待时间);发送数据
    • HAL_UART_DMAStop(&huart*)停止某个串口DMA传输 处理数据时一定要关闭防止数据被挤掉
    • HAL_UART_Receive_DMA(&huart*, 字符数组, 接收大小 );重新打开DMA传输并指定写入内存
  2. 串口定时报警程序
static void UART_TempSend()
{
	double linshi =0;

	linshi = PWM_Zhankongbi*3.3;			//根据题目要求:VIN>k×3.3 时,以 1s 为间隔自动上报当前的温度数据
	if(ADCRead_Num(1)>linshi || ADCRead_Num(2)> linshi) 
	{
		if(led1!=2 ){led1 =1;}

		if(time4_1S > 4)	//定时达到要求 重新上报
		{
			time4_1S = 0;
			memset(UARTTEMP,0,30); 
 			sprintf(UARTTEMP,"$%.2f\r\n",DS18B20_TEMP);
 			HAL_UART_Transmit(&huart1,(uint8_t *)UARTTEMP,sizeof(UARTTEMP),100);

		}
	}
	else if(led1!=0	){led1=5;}
}

static void UART_TN()
{
	if( DS18B20_TEMP> Tmm )
	{
		HAL_TIM_Base_Start_IT(&htim1);
	}
	else if	(DS18B20_TEMP < Tmm )
	{
		HAL_TIM_Base_Stop_IT(&htim1);
		if (tim1_LD8 != 0)tim1_LD8 = 3;
	}

}

2.添加重要驱动

我们需要编写温度传感器和II2的驱动文件添加进工程(不知道比赛会不会给,自己写一个也好)
DS18B20驱动
II2C驱动
数码管驱动
在这里插入图片描述
把文件添加进工程,顺手添加lcd.c
LCD驱动

3.II2C:

在main.c添加自定义的II2C读写函数(uint8_t)类型

uint16_t x24c02_read(uint8_t address)		//I2C读
{
	uint16_t val;
	
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	
	I2CSendByte(address);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0xa1);
	I2CWaitAck();
	val = I2CReceiveByte();
	I2CWaitAck();
	I2CStop();
	return(val);
}

void x24c02_write(uint8_t address,uint16_t info)	//I2C写
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	
	I2CSendByte(address);
	I2CWaitAck();
	I2CSendByte(info);
	I2CWaitAck();

	I2CStop();

}

读写案例:

//从0x00的位置读取一个字
xxx= x24c02_read(0x00);
//向0x00写入一个字
x24c02_write(0x00,(uint8_t) xxx);

4.DS18B20:

温度传感器读取案例:

变量 = ds18b20_read(); //注意这里读取出来的是十六位的数字 要除以16再取整使用

DS18B20_TEMP = ((int)((ds18b20_read()/16.0)*100)) ;
DS18B20_TEMP = DS18B20_TEMP/100;

5.数码管:

直接调用驱动内的函数就好
对应的表如下

//						0    1    2    3     4    5    6    7    8    9    A	B	C	  D		E   F   关
uint8_t Seg7[17] = { 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c, 0x39,0x4f,0x79,0x78,0x00};
SEG_DisplayValue(uint8_t Bit1,  uint8_t Bit2, uint8_t Bit3);
  • 例:
  • 在这里插入代码片

6.ADC:

接下来编写ADC顺序读取以及按序号取数据的函数,ADC在调用时会读取第一个通道的值,第二次调用读取第二个通道的值。

static double ADCRead(ADC_HandleTypeDef *hadcx)
{
	    //开启ADC1
    HAL_ADC_Start(&hadc2);
    //等待ADC转换完成,超时为100ms
    HAL_ADC_PollForConversion(&hadc2,100);
    //判断ADC是否转换成功
    if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc2),HAL_ADC_STATE_REG_EOC))
    {
	  
         //读取值
     HAL_ADC_GetValue(&hadc2);
    }
    
}
static double ADCRead_Num(uint8_t num)
{
	
	ADC_Value[1]= ADCRead(&hadc2); //读取第一个通道的值
	HAL_Delay(5);
	ADC_Value[2]= ADCRead(&hadc2);//读取第二个通道的值
	return ADC_Value[num];		//返回序号的值
}

这时题目的常用函数基本上都写好了,开始编写逻辑类的函数,按键处理以及页面显示,TIM中断类,定时等

7.LED:

LED与LCD复用,所以采用了一个锁存器来储存对LED的控制信号
在这里插入图片描述
在这里插入图片描述
在启用LE引脚时,可往锁存器写入八位二进制数据,0对应开1关。写满后关闭LE引脚,锁存器可以保持关闭前的八位状态。

  • 运行LCD之前先关闭所有LCD,防止LED乱闪
static void LEDClear() //关闭所有LED
{
	
	HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_SET);	//锁存器开
  	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_15|GPIO_PIN_9|GPIO_PIN_8,GPIO_PIN_SET); //LED全部熄灭
	HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_RESET);//锁存器关

}
  • 闪灯计时
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)	//tim1中断回调
{
	if(htim->Instance == TIM1)
	{
		if	   (tim1_LD8 == 0)		{	tim1_LD8 = 1;}
		else if(tim1_LD8 == 2)		{	tim1_LD8 = 4;}
	}
}

所有与LED闪烁有关的函数,整体思路如下

  • 计时1次后 判断需要闪哪个灯,然后进行一次锁存器复写,完成标记。
  • 计时2次 翻转状态。
  • 不需要闪灯时,将状态写为不在判定区域的任意数,要用时再写回来即可。
static void Led_bulle()
{
	if(tim1_LD8 == 1)
	{
		HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_SET);	//锁存器开
		if(led1 ==2 )	
		{	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15|GPIO_PIN_8,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_9,GPIO_PIN_SET);
		}
		else 
		{
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15|GPIO_PIN_8,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_9|GPIO_PIN_8,GPIO_PIN_SET);
		}
		HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_RESET);//锁存器关
		tim1_LD8 = 2;
	}
	else if (tim1_LD8  == 4)
	{
		HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_SET);	//锁存器开
 		if(led1 ==2)
		{
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_15|GPIO_PIN_9,GPIO_PIN_SET);
		}
		else{	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_15|GPIO_PIN_9|GPIO_PIN_8,GPIO_PIN_SET);	}
		
		HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_RESET);//锁存器关
		tim1_LD8 = 0;
	}
	else if (tim1_LD8 == 3)
	{
		tim1_LD8 = 0;
		HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_SET);	//锁存器开
 		if(led1 ==2)
		{
			HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_15|GPIO_PIN_9,GPIO_PIN_SET);
		}
		else{	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_15|GPIO_PIN_9|GPIO_PIN_8,GPIO_PIN_SET);	}
		
		HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_RESET);//锁存器关
	}
	if(led1 ==1	)
	{
		HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_SET);	//锁存器开
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET); 
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_15|GPIO_PIN_9,GPIO_PIN_SET);
		HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_RESET);//锁存器关
		led1 = 2;
	}
	else if (led1 == 5) 
	{	
		led1 = 0;
		HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_SET);	//锁存器开
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_11|GPIO_PIN_14|GPIO_PIN_10|GPIO_PIN_15|GPIO_PIN_9|GPIO_PIN_8,GPIO_PIN_SET);
		HAL_GPIO_WritePin(LEDLOCK_GPIO_Port, LEDLOCK_Pin,GPIO_PIN_RESET);//锁存器关
	}
}

8.PWM

在这里插入图片描述
先看PWM测量 一共要检测2个上升沿,1个下降沿

  • 在检测到第一个上升沿时,清空计数值,然后等待一个下降沿
  • 下降沿到来时,记录下tim的时间,清空计数值,等待第二个上升沿
  • 第二个上升沿来时,记录tim的时间,激活处理数据的函数,计算出占空比
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) //记录等待脉冲中的溢出次数
{
	    if(htim->Instance == TIM3)
		{
			if(PWMON == 1)	//脉冲检测1阶段
			{
				PWM_YICHU1++;
	
			}
			else if (PWMON == 2) //脉冲检测2阶段
			{
				PWM_YICHU2++;
			}
		}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)   // 脉冲捕捉
{
	if(htim ->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
	{
		if(PWMON == 1 && Setting == 1 )
		{
			PWMDW1 = __HAL_TIM_GetCounter(&htim3);
			__HAL_TIM_SetCounter(&htim3,0);
			PWMON = 2;
		}
	}
	else if(htim ->Channel == HAL_TIM_ACTIVE_CHANNEL_2	)
	{
		if(PWMON == 0)
		{
			__HAL_TIM_SetCounter(&htim3,0);
			PWMON = 1;
		}
		else	if(PWMON == 2)
		{
			PWMUP2 = __HAL_TIM_GetCounter(&htim3);
			__HAL_TIM_SetCounter(&htim3,0);
			PWMON = 3;
		}
	}
}

占空比计算公式 D=PD1/(PD1*频率/PU2) x 100%
频率在初始化tim时就决定了 170MHZ/预分频值170
PU1在我这里默认为0 作为起点

if (PWMON == 3	 )									//重新计算占空比
	{
			PWMDW1 =1000000/ (PWMDW1+50000*PWM_YICHU1); //ARR值为50000,所以真实计数值为 计数值+50000*溢出次数
			//PWMUP2 =1000000/ (PWMUP2+50000*PWM_YICHU2);
			PWM_Zhankongbi =(100* (PWMDW1 / (PWMDW1+1000000/(PWMUP2+50000*PWM_YICHU2))))+0.5 ;		//占空比计算
			sprintf(LCDTEMP,"    PWM2:%d%%    ",PWM_Zhankongbi); 
			LCD_DisplayStringLine(Line5,(uint8_t *)LCDTEMP); //显示占空比
				
			PWMON = 0;
			PWM_YICHU1 = 0;
			PWM_YICHU2 = 0;
	}

9.按键检测:

我并没有采用按键中断的方法,这会干扰PWM计算和LCD的写入,直接用扫描GPIO的方式获得按键值
读题
在这里插入图片描述
设置储存按键状态和切换模式的状态值,切换页面时先刷新LCD,防止字符显示错误。
在检测中设上一定的延时,防止多次触发。

static void yemian_JM()
{
	if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET ) //读取按键状态
	{
		
		Setting++;
		HAL_TIM_IC_Stop_IT(&htim3, TIM_CHANNEL_1);
		if (Setting == 3){Setting = 1;HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);}
		LCD_Clear(White);
		while(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET);
	}
	if(Setting == 2)
	{
		if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET  )//读取按键状态
		{
			SetOb++;
			HAL_Delay(200);
			if (SetOb == 3){SetOb =1;}
		}
		if(SetOb == 1)
		{
			if(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin)==GPIO_PIN_RESET )//读取按键状态
			{
				Tmm++;
				HAL_Delay(500);
				if(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin)==GPIO_PIN_RESET)	{Tmm+=9;}
			}
			else if(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin)==GPIO_PIN_RESET )//读取按键状态
			{
				Tmm--;
				HAL_Delay(500);
				if(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin)==GPIO_PIN_RESET)	{Tmm-=9;}
				
			}
		}
		else if(SetOb == 2)
		{
			if(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin)==RESET  )//读取按键状态
			{
				Xmm++;
				HAL_Delay(200);
			}
			else if(HAL_GPIO_ReadPin(KEY4_GPIO_Port,KEY4_Pin)==RESET )//读取按键状态
			{
				Xmm++;
				HAL_Delay(200);
			}
			if (Xmm > 2){ Xmm = 1;}		//超限设定
			else if (Xmm == 0){ Xmm = 1;}
			if (Tmm >40){ Tmm = 20;}
			else if (Tmm == 0	){ Tmm = 40;}
		}

	}

}

然后写LCD页面显示的函数

10.LCD:

  • LCD_DisplayStringLine(Line1,(uint8_t *)LCDTEMP);显示一排字符
  • LCD_Init();初始化
  • LCD_Clear(颜色);清空并以特定颜色填充屏幕
  • LCD_SetBackColor(颜色);设置背景颜色
  • LCD_SetTextColor(Blue);设置字符颜色
static void LCDLive()	
{
	if(Setting == 1)															//主页面
	{
		LCD_DisplayStringLine(Line0,(uint8_t *)"        Main       ");	
		sprintf(LCDTEMP,"    AO1:%.2lfV     ",ADCRead_Num(1));
		LCD_DisplayStringLine(Line1,(uint8_t *)LCDTEMP);	
		sprintf(LCDTEMP,"    AO2:%.2lfV     ",ADCRead_Num(2));
		LCD_DisplayStringLine(Line3,(uint8_t *)LCDTEMP);

		sprintf(LCDTEMP,"    TEMP:%.2lf C    ",DS18B20_TEMP);
		LCD_DisplayStringLine(Line7,(uint8_t *)LCDTEMP);
		sprintf(LCDTEMP,"    N:%d           ",N_Num);
		LCD_DisplayStringLine(Line9,(uint8_t *)LCDTEMP);
			if (PWMON == 3	 )									//重新计算占空比
			{
					PWMDW1 =1000000/ (PWMDW1+50000*PWM_YICHU1);
					//PWMUP2 =1000000/ (PWMUP2+50000*PWM_YICHU2);
					PWM_Zhankongbi =(100* (PWMDW1 / (PWMDW1+1000000/ (PWMUP2+50000*PWM_YICHU2))))+0.5 ;		
					
					sprintf(LCDTEMP,"    PWM2:%d%%    ",PWM_Zhankongbi);
					LCD_DisplayStringLine(Line5,(uint8_t *)LCDTEMP);
				
					PWMON = 0;
					PWM_YICHU1 = 0;
					PWM_YICHU2 = 0;
			}
	}

	else if(Setting == 2)														//设置模式
	{

		if(SetOb == 1)
		{
			LCD_DisplayStringLine(Line0,(uint8_t *)"       Para      ");
			sprintf(LCDTEMP,"    T: %d    ",Tmm);
			LCD_SetTextColor(Red);
			LCD_DisplayStringLine(Line2,(uint8_t *)LCDTEMP);
			LCD_SetTextColor(Blue);
			sprintf(LCDTEMP,"    X: AO%d    ",Xmm);
			LCD_DisplayStringLine(Line5,(uint8_t *)LCDTEMP);		
		}
		else if(SetOb == 2)
		{
			LCD_DisplayStringLine(Line0,(uint8_t *)"       Para      ");
			sprintf(LCDTEMP,"    T: %d    ",Tmm);
			LCD_DisplayStringLine(Line2,(uint8_t *)LCDTEMP);			
			sprintf(LCDTEMP,"    X: AO%d    ",Xmm);
			LCD_SetTextColor(Red);
			LCD_DisplayStringLine(Line5,(uint8_t *)LCDTEMP);
			LCD_SetTextColor(Blue);			
		}
	}
}

11.写完所有函数

整合工程 在主函数循环里调用就行了。

/* USER CODE BEGIN WHILE */
  while (1)
  {

	DS18B20_TEMP = ((int)((ds18b20_read()/16.0)*100)) ;
	DS18B20_TEMP = DS18B20_TEMP/100;
	if(IIC_huancun != DS18B20_TEMP)	//判断是否需要从EEPROM写数据
	{
		N_Num++;
		IIC_huancun = DS18B20_TEMP;
		x24c02_write(0x00,N_Num);
	}
	yemian_JM();
	LCDLive();
	UART_TempSend();
	UART_TN();
	Led_bulle();
	

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

最后

本人也是今年参加蓝桥杯,写这个教程就当复习了,祝大家得个好成绩。
完整工程

;原文链接:https://blog.csdn.net/qq_39536828/article/details/115381031
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文


随机推荐