蓝桥杯嵌入式(F103平台)开发问题记录~持续更新

本文详细介绍了STM32在LCD显示、LED控制、按键读取以及定时器应用方面的常见问题及其解决方案。内容涵盖LCD字符显示、数据覆盖、格式化输出、高亮选中参数、定时不准确、按键无反应、ADC数据读取等方面的故障排查和优化技巧。此外,还涉及了RTC时间显示、PWM输出、输入捕获等功能的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【LCD】

问题:数据长度变短后,上次的长数据数据依然显示在末尾

解决:液晶一行可正常显示20个ASCII字符,可使用字符串空格的方式避免长数据对短数据的覆盖

LCD_DisplayStringLine(Line0, (unsigned char *)"  hello lanqiao dasai");
// 解决字符串覆盖问题 (加空格)
LCD_DisplayStringLine(Line0, (unsigned char *)"  www.xatu.edu.cn    ");	

【LCD】

问题:液晶格式化显示数据

解决:添加头文件"stdio.h",使用sprintf函数,利用%进行格式化输出

// 常用格式化类型:
%d   有符号十进制整数
%u   无符号十进制整数
%x   无符号十六进制数
%o   无符号八进制数
%e   e指数科学计数法
%E   E指数科学计数法
%s   字符串
%c   字符
%f   浮点数,默认显示6位小数
%.nf 浮点数,精确小数位数为n
%#x  无符号十六进制数加前缀0x
%#o  无符号八进制数加前缀0
%%   百分号
%5d  十进制整数,长度为5(右对齐,空格填充)
%05d 十进制整数,长度为5(右对齐,0填充)	   
%-5d 十进制整数,长度为5(左对齐,空格填充)	
%+5d 十进制整数,长度为5(右对齐,空格填充,显示正负符号)
u8 display_buf[20];

// 格式化数据示例
sprintf((char *) display_buf, "%5dHz", 5000);
LCD_DisplayStringLine(Line3, display_buf);
sprintf((char *) display_buf, "%.5f", 3.1415926);
LCD_DisplayStringLine(Line4, display_buf);
sprintf((char *) display_buf, "%#X", 15);
LCD_DisplayStringLine(Line5, display_buf);
sprintf((char *) display_buf, "%o", 15);
LCD_DisplayStringLine(Line6, display_buf);
sprintf((char *) display_buf, "%+5d", -15);
LCD_DisplayStringLine(Line7, display_buf);

【LCD】

问题:精确控制字符显示位置

解决:液晶显示屏长320,宽240,共划分为10行,编号1~10(Line0~Line9),每行大小320*24像素,每个ASCII字符占16*24个像素(Fonts.h中已经定义,支持0x20到0x7E)

每行最多正常显示20个ASCII字符,共划分20列,编号1~20(0~19),整屏最多显示200字符

每一行的像素起点位置定义如下(lcd.h中可以找到)

#define Line0          0
#define Line1          24
#define Line2          48
#define Line3          72
#define Line4          96
#define Line5          120
#define Line6          144
#define Line7          168
#define Line8          192
#define Line9          216
图1 液晶行列分布示意

可以使用LCD_DisplayChar()函数指定单个字符显示,参数依次为行参数、列像素参数、显示字符

图2 液晶1行的320列像素序号分布

对液晶每一行来说,液晶像素序号从右向左编号,依次为(左)319,318,317......0(右),指定列像素光标位置后,从当前像素位置开始向右写入字符,然后光标向右移动到一个下一像素位置

(可以理解为指定319,从319写到304;指定15,从15写到0),注意的是,如果指定的是0,写完0后,移动的下一位是319;如果指定大于319,比如330,依然会从319开始向右写

1个字符占用16*24个像素位置,先写一行像素的16个像素宽度,然后行像素位置加1,开始写下一行像素,直到24行全部写入,一个字符写入完成。

底层代码如下(在lcd.c中可以找到)

/*******************************************************************************
* Function Name  : LCD_DrawChar
* Description    : Draws a character on LCD.
* Input          : - Xpos: the Line where to display the character shape.
*                    This parameter can be one of the following values:
*                       - Linex: where x can be 0..9
*                  - Ypos: start column address.
*                  - c: pointer to the character data.
* Output         : None
* Return         : None
*******************************************************************************/
void LCD_DrawChar(u8 Xpos, u16 Ypos, uc16 *c)
{
	u32 index = 0, i = 0;
	u8 Xaddress = 0;
   
	Xaddress = Xpos;
	LCD_SetCursor(Xaddress, Ypos);
  
	for(index = 0; index < 24; index++)
	{
		LCD_WriteRAM_Prepare(); /* Prepare to write GRAM */
		for(i = 0; i < 16; i++)
		{
			if((c[index] & (1 << i)) == 0x00)
			{
				LCD_WriteRAM(BackColor);
			}
			else
			{
				LCD_WriteRAM(TextColor);
			}
		}
		Xaddress++;
		LCD_SetCursor(Xaddress, Ypos);
	}
}

例如,图1中在第1行第7列显示字符‘D’,则行参数为Line0,列像素参数为319-16*6,显示字符为‘D’

LCD_DisplayChar(Line0, 319-16*6, 'D');

使用两种指定列像素方式显示一行字符示例: 

u8 i = 0;
for(i=0; i<20; i++)
{
	// 第一种显示方法
	LCD_DisplayChar(Line1, 16*(20-i)-1, i+'0');
	// 第二种显示方法
	LCD_DisplayChar(Line2, 319-16*i, i+'0');
}

【LCD】

问题:高亮选中参数,或选中参数闪烁

解决:精确位置控制+背景颜色改变(LCD_SetBackColor、LCD_SetTextColor)

例如:在时钟参数调整中,要求在选择时、分、秒,分别高亮显示对应参数,示例程序中使用红色背景高亮显示

u8 upload_time[3] = {0, 1, 0};

H1 = upload_time[0] / 10;
H2 = upload_time[0] % 10;
M1 = upload_time[1] / 10;
M2 = upload_time[1] % 10;
S1 = upload_time[2] / 10;
S2 = upload_time[2] % 10;

u8 choose = 2;
u8 i = 6;

sprintf((char *)display_buf, "      Setting      ");
LCD_DisplayStringLine(Line3, display_buf);

if(choose == 1)
{
	LCD_SetBackColor(Red);
	LCD_SetTextColor(White);	
}
LCD_DisplayChar(Line5, 319-16*(i+0), H1 + '0');
LCD_DisplayChar(Line5, 319-16*(i+1), H2 + '0');
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
LCD_DisplayChar(Line5, 319-16*(i+2), '-');
if(choose == 2)
{
	LCD_SetBackColor(Red);
	LCD_SetTextColor(White);		
}
LCD_DisplayChar(Line5, 319-16*(i+3), M1 + '0');
LCD_DisplayChar(Line5, 319-16*(i+4), M2 + '0');
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);

LCD_DisplayChar(Line5, 319-16*(i+5), '-');

if(choose == 3)
{
	LCD_SetBackColor(Red);
	LCD_SetTextColor(White);	
}
LCD_DisplayChar(Line5, 319-16*(i+6), S1 + '0');
LCD_DisplayChar(Line5, 319-16*(i+7), S2 + '0');
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
图3 高亮显示选中参数示意

选择参数闪烁的代码参考

u8 upload_time[3] = {0, 0, 0};

H1 = upload_time[0] / 10;
H2 = upload_time[0] % 10;
M1 = upload_time[1] / 10;
M2 = upload_time[1] % 10;
S1 = upload_time[2] / 10;
S2 = upload_time[2] % 10;

u8 choose = 1;
u8 i = 6;
u8 LCD_Blink = 0;
extern u8 Flag_200ms;

if(Flag_200ms)	
{
    Flag_200ms = 0;
    LCD_Blink = ++LCD_Blink % 2;
}

sprintf((char *)display_buf, "      Setting      ");
LCD_DisplayStringLine(Line3, display_buf);

if(choose == 0)
{
	LCD_DisplayChar(Line5, 319-16*(i+0), H1 + '0');
	LCD_DisplayChar(Line5, 319-16*(i+1), H2 + '0');
	LCD_DisplayChar(Line5, 319-16*(i+2), '-');	
	LCD_DisplayChar(Line5, 319-16*(i+3), M1 + '0');
	LCD_DisplayChar(Line5, 319-16*(i+4), M2 + '0');
	LCD_DisplayChar(Line5, 319-16*(i+5), '-');
	LCD_DisplayChar(Line5, 319-16*(i+6), S1 + '0');
	LCD_DisplayChar(Line5, 319-16*(i+7), S2 + '0');	
}
else if(choose == 1)
{
	if(LCD_Blink == 0)
	{
		LCD_DisplayChar(Line5, 319-16*(i+0), H1 + '0');
		LCD_DisplayChar(Line5, 319-16*(i+1), H2 + '0');	
	}
	else
	{
		LCD_DisplayChar(Line5, 319-16*(i+0), ' ');
		LCD_DisplayChar(Line5, 319-16*(i+1), ' ');
	}
	LCD_DisplayChar(Line5, 319-16*(i+2), '-');	
	LCD_DisplayChar(Line5, 319-16*(i+3), M1 + '0');
	LCD_DisplayChar(Line5, 319-16*(i+4), M2 + '0');
	LCD_DisplayChar(Line5, 319-16*(i+5), '-');
	LCD_DisplayChar(Line5, 319-16*(i+6), S1 + '0');
	LCD_DisplayChar(Line5, 319-16*(i+7), S2 + '0');	
}
else if(choose == 2)
{
	LCD_DisplayChar(Line5, 319-16*(i+0), H1 + '0');
	LCD_DisplayChar(Line5, 319-16*(i+1), H2 + '0');	
	LCD_DisplayChar(Line5, 319-16*(i+2), '-');	
	if(LCD_Blink == 0)
	{
		LCD_DisplayChar(Line5, 319-16*(i+3), M1 + '0');
		LCD_DisplayChar(Line5, 319-16*(i+4), M2 + '0');	
	}
	else
	{
		LCD_DisplayChar(Line5, 319-16*(i+3), ' ');
		LCD_DisplayChar(Line5, 319-1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

乐观的lishan

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

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

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

打赏作者

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

抵扣说明:

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

余额充值