【STM32G4】嵌入式蓝桥杯国赛备赛——HAL库——ds18b20温度传感器——数码管——串口收发——EEPROM——第10届真题练习

          Hi~,大家好呀,今天给大家分享的是嵌入式国赛第10届的真题详解。这届题目较前后几届难度略大,非常适合我们练手。

        好了废话不多说,我们直接进入正题


        首先理清我们需要用到的外设

 

         可以看到我们分别要完成对以下模块的配置:

        其中出现了省赛没有出现的外设:温度传感器ds18b20以及数码管。

        先上这两个外设的初始化函数:

int16_t ds18b20_read(void)
{
	uint8_t TH;
	uint8_t TL;
	
	ow_reset();
	ow_byte_wr(OW_SKIP_ROM);
	ow_byte_wr(DS18B20_CONVERT);
	
	ow_reset();
	ow_byte_wr(OW_SKIP_ROM);
	ow_byte_wr(DS18B20_READ);
	
	TL = ow_byte_rd();
	TH = ow_byte_rd();
	
	return (((TH << 8) | TL) & 0x7FFF);
}

                                                                    ds18b20

#include "seg\seg.h"

uint8_t Seg[17] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, 0x00};


//初始化函数
void Seg_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	
	__HAL_RCC_GPIOA_CLK_ENABLE();
	
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);
	
	GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	
	
}


//显示函数
void Seg_Display_Value(uint8_t Bit1, uint8_t Bit2, uint8_t Bit3)
{
	uint8_t Temp = 0;
	uint8_t	i = 0;
	
	SCK_L;
	RCK_L;
	
	Temp = Seg[Bit3];
	for(i = 0; i < 8; i++)
	{
		if(Temp & (0x80 >> i))
			SER_H;		
		else
			SER_L;

		
		SCK_H;
		SCK_L;
	}
	
	Temp = Seg[Bit2];
	for(i = 0; i < 8; i++)
	{
		if(Temp & (0x80 >> i))
		{
			SER_H;		
		}
		else
		{
			SER_L;
		}
		
		SCK_H;
		SCK_L;
	}
	
	Temp = Seg[Bit1];
	for(i = 0; i < 8; i++)
	{
		if(Temp & (0x80 >> i))
		{
			SER_H;		
		}
		else
		{
			SER_L;
		}
	
		SCK_H;
		SCK_L;
	}
	
	RCK_H;
	
}
//头文件引用
#ifndef __SEG_H__
#define __SEG_H__

#include "main.h"

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

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

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


void Seg_Init(void);
void Seg_Display_Value(uint8_t Bit1, uint8_t Bit2, uint8_t Bit3);


#endif

                                                                      seg

        我总结了一下我在这道题中碰到的难点,以及自己写的有意思的地方,这里分享给大家:难点在于串口的收发部分以及数据的存储部分。

这一年的题使用了大量串口的数据处理,以及对数据有效性的判断:

 

以及在AT24C02数据存储中需要存储16字节的数据

 

首先我们对串口部分进行讲解:

接收中断函数:
 

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(pRx_Buf == 0)
	{
		Uart_Set_Point = uwTick;
		Uart_Flag = 1;
	}
	if(Uart_Flag == 1)
	{
		Rx_Buf[pRx_Buf] = Rx_Buffer;
		pRx_Buf++;
	}

	HAL_UART_Receive_IT(&huart1, &Rx_Buffer, 1);	
	
}

我使用了一个字节一个字节接收的方式将数据先缓存在Rx_Buffer中,再将其转入数组,并且在首次接收到数据后进行时间打点,纪录此处的时间Uart_Set_Point。

然后是数据处理函数:

void Uart_Proc(void)
{
	if(uwTick - uwTick_Uart_Set_Point < 200)	return;
	uwTick_Uart_Set_Point = uwTick;
	
	
	Uart_Count_Point++;
	if(Uart_Count_Point > 5 && AO_Flag)
	{
		printf("&%.2f\r\n", Temp);
		Uart_Count_Point = 0;
	}
	
	if(uwTick - Uart_Set_Point >= 200 && uwTick - Uart_Set_Point < 400)
	{
		if(Rx_Buf[0] == 'A' && Rx_Buf[1] == 'T' && Rx_Buf[2] == 0x0D && Rx_Buf[3] == 0x0A)
		{
			printf("&%.2f\r\n", Temp);
		}
		else if(Rx_Buf[0] == 'P' && Rx_Buf[1] == 'A' && Rx_Buf[2] == 'R' && Rx_Buf[3] == 'A' 
			&& Rx_Buf[4] == 0x0D && Rx_Buf[5] == 0x0A)
		{
			printf("#%d,AO%d\r\n", Temp_Compare_Disp, AO_Seclet_Disp + 1);
		}
		else
		{
			printf("no");
		}
		
		Uart_Flag = 0;
		pRx_Buf = 0;
	}

}

在中断函数打点的时间在此函数内处理,将接收到的数据在0.2s左右进行数据的处理与分析。

EEPROM的处理

因为EEPROM一次只能存储一个字节,那么如果我们想按照题意存储一个0~65535内的数据,该如何操作呢?

 为此我定义了一个联合体他们N_16,和N_8[2]指向了同一块空间,即他们共用了这一片16bit的空间范围。

这样只要把N_R.N_8[0],与N_R.N_8[1]分别存储在EEPROM内,然后再进行读取,在使用时直接使用N_R.N_16,就可以优雅的得到我们想要的16位的数据啦。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楼鱼睡觉的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值