ARM裸机——FS2410按键控制LED灯(查询方式)

一、开发环境

1、硬件平台:FS2410(s3c2410)

2、主机:Ubuntu 10.10

二、硬件的原理图(LED和按键)

1、LED灯的原理图:

2、按键的原理图:

按键的接线资源:

KSCAN0 -> GPE11    KSCAN1 -> GPG6     KSCAN2 -> GPE13      KSCAN3 -> GPG2

EINT0  -> GPF0     EINT2  -> GPF2    EINT11 -> GPG3     EINT19 -> GPG11


三、程序的主要原理:

主要涉及到K1,K2, K3, K4这四个按键,要用查询的方式进行判断哪个键被按下去了,因此将EINT11, EINT19设置为输入,用于读取,将KSCAN0,KSCAN1, KSACAN2,设置为输出,并分别设置为0,1,1或1,0,1或1,1,0这三种情况下,这样可用于区分K1、K2、K3中哪个键按下去,例如先让KSCAN0~2 = 011,那么K1被按下时,EINT19才会变为低电平,这时K2按下时,EINT19不会变低,这样就区分了按键K1和K2,区分其它按键原理一样。

 

四、寄存器的配置

1、有关LED的寄存器的配置:(设置GPF4-GPF7为输出)


2、按键方面涉及到寄存器配置(设置相关寄存器输入输出):

  

    

  

     

                        

     

 

五、程序的详细代码:

led_key.c:(s3c2410.h头文件可在keil目录下找到,由s3c2440.h重命名得来)

#include "s3c2410.h"

void delay(long long max)      //延迟函数
{
	for(; max > 0; max--);

}

int main(void)
{
	int read_value;

	GPFCON = GPFCON & (~(0xff) << 8) | (0x55 << 8);     //设置4个LED灯为输出(GPF4-GPF7输出)
	GPFDAT |= (0xf << 4);       //先将4个灯都熄灭掉

	GPGCON = (0 << 7) | (1 << 12) | (0 << 23);       //GPG3, GPG11 输入,GPG6, GPE11, GPE13输出
	GPECON =  (1 << 22) | (1 << 26);

	while(1)
	{
		GPEDAT &= (0 << 11);      //将GPE11置0,同时将GPE13和GPG6置1
		GPEDAT |= (1 << 13);
		GPGDAT |= (1 << 6);

		read_value = GPGDAT & 0x808;      //读取GPG11和GPG3的输入值

		if((read_value & 0x800) == 0)       //判断GPG11输入是否为0,以此判断K1键是否按下
		{
			read_value = 0x800;
			delay(200000);        //按键去抖

			if((read_value &= GPGDAT) == 0)
			{
				if((GPFDAT & (1 << 4)) == 0)      //判断D12是否亮着,如果亮着则熄灭,反之相反
					GPFDAT |= (0x1 << 4);
				else
					GPFDAT &= (0xe << 4);
			}
		}
		else
		{
			if((read_value & 0x8) == 0)     //判断GPG3输入的值是否为0, 以此K4键是否按下
			{
				read_value = 0x8;
				delay(200000);        //按键去抖

				if((read_value &= GPGDAT) == 0)
				{
					if((GPFDAT & (0x8 << 4)) == 0)     //判断D9是都亮着,如果亮着则熄灭,反之相反
						GPFDAT |= (0x8 << 4);
					else
						GPFDAT &= (0x7 << 4);
				}
			}
		}


		GPEDAT |= (1 << 11);     //将GPE11和GPE13置1,同时将GPG6置0
 		GPEDAT |= (1 << 13);
		GPGDAT &= (0 << 6);
	
		read_value = GPGDAT & (0x8 << 8);       //读取GPG11的值
						        
		if(read_value == 0)       //判断GPG11是否输入0,以此判断K2键按下
		{   
			read_value = 0x800;  
			delay(200000);       //按键去抖
															           
			if((read_value &= GPGDAT) == 0)
			{  
				if((GPFDAT & (0x2 << 4)) == 0)     //判断D11是否亮着, 如果亮着则熄灭,反之相反
					GPFDAT |= (0x2 << 4);  
				else  
					GPFDAT &= (0xd << 4);  
			}  
		} 

		GPEDAT &= (0 << 13);      //将GPE13置0, 同时将GPE11和GPG6置1
		GPEDAT |= (1 << 11);
		GPGDAT |= (1 << 6);

		read_value = GPGDAT & 0x800;           //读取GPG11的值

		if(read_value == 0)        //判断GPG11是否为0,以此判断K3键是否按下
		{
			read_value = 0x800;
			delay(200000);      //按键去抖,延迟一段时间

			if((read_value &= GPGDAT) == 0)
			{
				if((GPFDAT & (0x4 << 4)) == 0)      //判断D10是否亮着,如果亮着则熄灭,反之相反
					GPFDAT |= (0x4 << 4);
				else
					GPFDAT &= (0xb << 4);
			}
		}
	}

	return 0;
}

Makefile:

led.bin: start.S led_key.c
	arm-none-linux-gnueabi-gcc -c start.S -o start.o
	arm-none-linux-gnueabi-gcc -c led_key.c -o led_key.o
	arm-none-linux-gnueabi-ld -Ttext 0x30008000 start.o led_key.o -o led_key
	arm-none-linux-gnueabi-objcopy -O binary -S led_key led_key.bin

clean:
	rm -f *.o led_key.bin

启动文件start.S:

.text
.global _start
_start:
#define WATCHDOG 0x53000000
	ldr r0, =WATCHDOG
	mov r1, #0
	str r1, [r0]

	ldr sp, =1024*4
	bl main

loop:
	b loop

然后在开发板的uboot上执行以下命令:

tftp 30008000 led_key.bin

go 30008000



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F103C8T6是一款常用的单片机,它基于ARM Cortex-M3内核,具有丰富的外设资源。HAL库(Hardware Abstraction Layer)是ST公司提供的一套硬件抽象层库,可以简化对STM32外设的操作。 要实现按键控制LED亮度,可以按照以下步骤进行: 1. 初始化GPIO:首先需要初始化按键LED所连接的GPIO引脚。使用HAL库提供的函数可以方便地进行GPIO初始化,设置引脚为输入或输出模式。 2. 配置中断:为了实现按键的响应,可以配置外部中断。当按键按下时,触发中断,并执行相应的中断服务函数。 3. 编写中断服务函数:在中断服务函数中,可以编写代码来控制LED的亮度。可以通过改变LED的PWM占空比来实现不同的亮度调节。 4. 启动中断:在主函数中,启动外部中断,使其开始监听按键的状态变化。 下面是一个简单的示例代码,演示了如何使用STM32F103C8T6和HAL库实现按键控制LED亮度: ```c #include "stm32f1xx_hal.h" // 定义LED引脚和按键引脚 #define LED_PIN GPIO_PIN_13 #define LED_PORT GPIOC #define KEY_PIN GPIO_PIN_0 #define KEY_PORT GPIOA // 定义PWM相关参数 #define PWM_PERIOD 1000 // PWM周期 #define PWM_CHANNEL TIM_CHANNEL_1 // 使用的PWM通道 // 全局变量 TIM_HandleTypeDef htim; uint32_t pwmValue = 0; // PWM占空比 // 按键中断回调函数 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin == KEY_PIN) { // 按键按下时,增加PWM占空比 pwmValue += 100; if (pwmValue > PWM_PERIOD) { pwmValue = 0; } __HAL_TIM_SET_COMPARE(&htim, PWM_CHANNEL, pwmValue); } } int main(void) { // 初始化HAL库 HAL_Init(); // 初始化时钟 SystemClock_Config(); // 初始化GPIO GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = LED_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = KEY_PIN; GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(KEY_PORT, &GPIO_InitStruct); // 初始化定时器 __HAL_RCC_TIM3_CLK_ENABLE(); htim.Instance = TIM3; htim.Init.Prescaler = 0; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = PWM_PERIOD - 1; htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim); TIM_OC_InitTypeDef sConfigOC = {0}; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = pwmValue; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, PWM_CHANNEL); HAL_TIM_PWM_Start(&htim, PWM_CHANNEL); // 启动中断 HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI0_IRQn); while (1) { // 主循环 } } // 系统时钟配置函数 void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值