組み込みシステム実験 - [Xuanwu F103 開発ボード] 4 つの小さなライトと 4 つの小さなライトを 2 つの照明モードで順番に点灯し、KEY1 を使用して照明モードの切り替えを制御します

1. 実験の目的

スモールライト4個連続点灯とスモールライト4個全点灯の2つの点灯モードがあり、KEY1で点灯モードを切り替えることができます。

2. 実験のアイデア:

(1) サンプルプログラムの解析

#include "stm32f10x.h"
typedef unsigned int u32; 
void delay(u32 i)
{
    
    
	while(i--);
}
int main(void)
{
    
    
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	while(1)
	{
    
    
		GPIO_Write(GPIOB, 0x0);
		delay(0x2FFFFF);
		GPIO_Write(GPIOB, 0x20);
		delay(0x2FFFFF);
	}			
}

1. GPIO のポート レジスタにデータを書き込む、またはデータを読み取る手順:

① 制御ポート (GPIOx) のクロック イネーブル レジスタを開きます (GPIO はすべて APB2 にあります)。RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx, ENABLE);
② を使用して GPIO ピンを選択し、GPIO_InitStructure.GPIO_Pin = GPIO_Pin_y;
③ を使用して選択したピンの速度と動作ステータスを設定します。
設定され②``③たパラメータを使用して、GPIO_Init(GPIOx, &GPIO_InitStructure);GPIOxレジスタ

2.GPIO_書き込み

すべての GPIO ピンの ODR レジスタに一度にデータを書き込みます (GPIO_WriteBitその後、一度に指定されたピンの ODR レジスタにのみ書き込みます (一度に 1 ビットのみ書き込みます))

3. 点滅ライトを制御する

GPIOB の PB5 ピンの動作モードをプッシュプル出力に設定すると、GPIO の PB5 の値 (サンプル コードに対応GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5) が 1 の場合、LED0 のレベルがハイレベルになり、小さなライトがオフになり、それ以外の場合は LED0 が点灯します。がオンになっています。

	while(1)
	{
    
    
		//PB5的ODR为0,点亮
		GPIO_Write(GPIOB, 0x0);
		delay(0x2FFFFF);
		//0x20即为GPIO_Pin_5,0x20对应的二进制数为
		//0b100000,从右向左数,从第0位开始的第5位为1,
		//所以下面这行代码的意思就是设置PB5的ODR为1
		//所以在推挽输出下,LED0为高电平,LED0处小灯熄灭
		GPIO_Write(GPIOB, 0x20);
		delay(0x2FFFFF);
	}			

ここに画像の説明を挿入ここに画像の説明を挿入

(2) スモールライト4灯の同時点灯を実現(本紙はPB5、PB6、PB7、PB10を制御)

(追記:PB8はブザーです。そのピンは使用しないでください)
(ワイヤーを使用して、この4つのピンをスモールライトに対応するワイヤーに接続してください)

PB5 でスモールライトを点灯する原理に従って、PB6、PB7、および PB10 に対応するピンの対応するパラメータを初期化して、これらのピンの対応するビットを 1 に設定するだけです。コードは以下のように表示されます。

#include "stm32f10x.h"
typedef unsigned int u32; 
void delay(u32 i)
{
    
    
	while(i--);
}
int main(void)
{
    
    
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	while(1)
	{
    
    
		//ps:此处由于向GPIOB所有管脚都写入0,所以只要是上面初始化
		//过的设置为推挽输出模式的管脚,如果下下条Write语句没有把
		//对应端口置1,则这样的管脚导线连接的小灯会点亮
		GPIO_Write(GPIOB, 0x0);
		delay(0x2FFFFF);
		GPIO_Write(GPIOB, GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10);
		delay(0x2FFFFF);
	}			
}

(3) 4つの小さなライト(回転灯)の連続点灯を実現

原理は上記と同じで、小さなライトを消すたびに小さなライトを順番に残すだけです。コードは次のとおりです。 ps: ライトがオンになるたびに、使用されている方法
によりGPIO_Write、他のランプも同時に消灯します (4 つのランプのうち)

#include "stm32f10x.h"
typedef unsigned int u32; 
void delay(u32 i)
{
    
    
	while(i--);
}
int main(void)
{
    
    
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	while(1)
	{
    
    
		//点亮第1个灯,熄灭其他三个灯
		GPIO_Write(GPIOB, GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10);
		delay(0x2FFFFF);
		//点亮第2个灯,熄灭其他三个灯
		GPIO_Write(GPIOB, GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_10);
		delay(0x2FFFFF);
		//点亮第3个灯,熄灭其他三个灯
		GPIO_Write(GPIOB, GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_10);
		delay(0x2FFFFF);
		//点亮第4个灯,熄灭其他三个灯
		GPIO_Write(GPIOB, GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);
		delay(0x2FFFFF);
	}			
}

(4) KEY1 を使用して上記 2 つの照明モードの切り替えを制御します

下図のKEY1の回路図により、KEY1に対応するPE3がプルダウン入力の場合、KEY1を押しても押さなくてもKEY1のレベルは変化せず、意味がありません。そこで PE3 をプルアップ入力に設定し、KEY1 が押されると KEY1 のレベルが Low となり、PE3 の対応する IDR は 0、それ以外の場合は 1 になり、KEY1 が押されたかどうかを判断します。
ここに画像の説明を挿入
PE3 の IDR データを読み込むメソッドを使用しGPIO_ReadInputDataBit、PE3 の動作モードをプルアップ入力に設定するため、要件を満たすコードは次のように設計されます。

#include "stm32f10x.h"
#include<stdio.h>
void delay(u32 i)
{
    
    
 while(i--);
}
#define SYSCLK      72000000
void delay_us(unsigned int us)
{
    
    
	SysTick->LOAD = us * (SYSCLK / 1000000) - 1;
	//SysTick->VAL降为0时的时候,开始启动计时器
	//因此若其初值为0,则即时启动计时器
	SysTick->VAL = 0;
	SysTick->CTRL = (1 << 2) | (1 << 0);
	while ((SysTick->CTRL & (1 << 16)) == 0);
	SysTick->CTRL = 0;
}

int main(void)
{
    
    
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
 
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
		GPIO_InitStructure.GPIO_Pin = 0;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
		GPIO_Init(GPIOE, &GPIO_InitStructure);	

	int mode = 0;
	while(1)
	{
    
    
		//something maybe not  that good
		// when clicked key1, and press it too long to program go through a if or else block. program will meet
		// this first if ,and even you haven't press key1 again, mode will change
		
		// 只有按钮处于按下状态时才能进入这个if语句执行mode取反
		if( GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) == 0)
		{
    
    mode = ~mode;}
		//四个灯顺序点亮
		if(mode)
		{
    
    
			GPIO_Write(GPIOB,  GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10 );
			delay(0x2FFFFF);
			GPIO_Write(GPIOB,  GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_10 );
			delay(0x2FFFFF);
			GPIO_Write(GPIOB,  GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_10 );
			delay(0x2FFFFF);
			GPIO_Write(GPIOB,  GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 );
			delay(0x2FFFFF);
		} //end of second if
		// 四个灯同时点亮
		else
		{
    
    
			GPIO_ResetBits(GPIOB,GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10);
			delay(0x2FFFFF);
			GPIO_Write(GPIOB, GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10 );
			delay(0x2FFFFF);
		} //end of else  
	} //end of while
} //end of main

おすすめ

転載: blog.csdn.net/weixin_52111404/article/details/129610623