蓝桥杯嵌入式第八届程序设计

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

前言

一、题目分析

二、代码

1.定义变量

2.按键

3.处理数据

4.其他函数

5.每一个状态

5.1状态0

5.2状态1

5.3状态2

5.4状态3

5.5状态4

5.6状态5

5.7状态6

5.8状态7

5.9状态8

6主程序

总结


前言

蓝桥杯嵌入式赛道练习,只是记录自己的练习代码,如果有误,欢迎指出!!!

一、题目分析

这是我的第一个练习,所以看到题目有点懵,感觉不难,但是无从下手,所有在写完一些基础的程序后,参考了哔哩哔哩Up主蚂蚁工厂分析

二、代码

1.定义变量

extern Keys keys[4]; // 按键数组

uchar Led = 0;

RTC_TimeTypeDef T;                         // RTC时间

RTC_DateTypeDef D;                         // RTC日期

uint ral_time;                             // 当前时间

uint last_time;                            // 上一次的时间

int ral_floor;                             // 目前所在楼层

int Floor[3] = {0, 0, 0};                  // 要运行的楼层数组

int Up[4] = {0, 0, 0, 0};                  // 要上升运行的楼层数组

int down[4] = {0, 0, 0, 0};                // 要下降运行的楼层数组

int p_arrUp = 0, p_arrdown = 0, p_run = 0; // 指向数组的运行位置

char text[30];                             // LCD打印

int class_state;                           // 运行的步骤

2.按键

Keys keys[4]={0,0,0};//按键函数



void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//识别按键并消抖

{

    if(htim->Instance==TIM4)//判断中断是不是定时器4,定时器设置时间是10ms

    {

        keys[0].key_ral=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);//更新按键电平

        keys[1].key_ral=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);

        keys[2].key_ral=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);

        keys[3].key_ral=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);

        for(int i=0;i<4;i++)

        {

            switch(keys[i].key_sta)//判断按键

                {

                    case 0:

                    {

                        if(keys[i].key_ral==0)

                        {

                            keys[i].key_sta=1;                          

                        }

                    }break;

                    case 1:

                    {

                        if(keys[i].key_ral==0)

                        {

                            keys[i].key_sta=2;

                            keys[i].key_flag=1;                        

                        }

                        else

                        {

                            keys[i].key_sta=0;

                        }

                    }break;

                    case 2:

                    {
                        if(keys[i].key_ral==1)

                        {

                            keys[i].key_sta=0;

                        }

                    }break;

                }

        }

    }

}

/// @brief 读按键

/// @param  空

void Read_key(void)

{

    if (keys[0].key_flag == 1)

    {

        Led |= 1; // 写Led

        if (keys[0].key_reapt++ == 0)

        {

            tianarr(1); // 把按键写入数组

        }

        GetSecd();

        last_time = ral_time; // 更新时间

        keys[0].key_flag = 0;

    }

    if (keys[1].key_flag == 1)

    {

        Led |= 0x02;

        if (keys[1].key_reapt++ == 0)

        {

            tianarr(2);

        }

        GetSecd();

        last_time = ral_time;

        keys[1].key_flag = 0;

    }

    if (keys[2].key_flag == 1)

    {

        Led |= 0x04;

        if (keys[2].key_reapt++ == 0)

        {

            tianarr(3);

        }

        GetSecd();

        last_time = ral_time;

        keys[2].key_flag = 0;

    }

    if (keys[3].key_flag == 1)

    {

        Led |= 0x08;

        if (keys[3].key_reapt++ == 0)

        {
            tianarr(4);
        }

        GetSecd();

        last_time = ral_time;

        keys[3].key_flag = 0;

    }

    Led &= ~(1 << (ral_floor - 1));

    LedDisp(~(Led)); // 写Led

}

3.处理数据

处理按键的数据,运行后数组的数据顺序为运行的楼层顺序

void tianarr(int x) // 填数列

{
    if (x > ral_floor)
    {
        Up[p_arrUp++] = x;
        maopao(Up);
    }
    else if (x < ral_floor)
    {
        down[p_arrdown++] = x;
        maopao(Up);
    }
}

void maopao(int *arr) // 排序
{
    int temp, i, j;
    for (i = 0; i < 3; i++)
    {
        for (j = 3; j > i; j--)
        {
            if (arr[j] > arr[j - 1])
            {
                temp = arr[j - 1];
                arr[j - 1] = arr[j];
                arr[j] = temp;
            }
        }
    }
}

void arrCap(void) // 合并数列

{
    int i, j = 0;
    for (i = 0; i < 3; i++)
    {
        if (i < p_arrUp)
        {
            Floor[i] = Up[p_arrUp - i - 1];
            Up[p_arrUp - i - 1] = 0;
        }
        else
        {
           Floor[i] = down[j];
            down[j++] = 0;
        }
    }

    for (i = 0; i < 3; i++)
    {
        keys[i].key_reapt = 0;

    }
}

4.其他函数

void DispLcD(void) // Led显示

{
    LCD_DisplayStringLine(Line7, (uint8_t *)text);
    sprintf(text, "     %2d:%2d:%2d", T.Hours, T.Minutes, T.Seconds);
    LCD_DisplayStringLine(Line6, (uint8_t *)text);
    sprintf(text, "        %d", ral_floor);
    LCD_DisplayStringLine(Line5, (uint8_t *)text);
}
void GetSecd(void) // 得到时间
{
    HAL_RTC_GetTime(&hrtc, &T, RTC_FORMAT_BIN); // 获取RTC
    HAL_RTC_GetDate(&hrtc, &D, RTC_FORMAT_BIN);
    ral_time = T.Hours * 3600 + T.Minutes * 60 + T.Seconds;
}

5.每一个状态

5.1状态0


       

		case 0:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);
			GetSecd(); // 更新时间
			if (ral_time - last_time > 1 && (Up[0] || down[0]))//当最后一次按键按键1s后并且有数据才会进入下一个阶段
			{
				class_state = 1;
				last_time = ral_time;
				arrCap();
			}
			else
			{
				Read_key();
			}
		}
		break;

5.2状态1

	case 1:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);
			__HAL_TIM_SetCompare(&htim17, TIM_CHANNEL_1, 50);	  // 设置占空比50%
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // 设置PA5低电平
			HAL_TIM_PWM_Start(&htim17, TIM_CHANNEL_1);			  // 开启PWM
			class_state = 2;
			GetSecd(); // 更新时间
			last_time = ral_time;
		}
		break;

5.3状态2

case 2:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);

			GetSecd(); // 更新时间
			if (ral_time - last_time > 4)
			{
				class_state = 3;
				HAL_TIM_PWM_Stop(&htim17, TIM_CHANNEL_1);//停止PWM
				last_time = ral_time;
			}
			else
			{
				LedClose();
			}
		}
		break;

5.4状态3

		case 3:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);
			if (Floor[p_run] > ral_floor)//判断上升还是下降
			{
				__HAL_TIM_SetCompare(&htim16, TIM_CHANNEL_1, 80);
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
			}
			else
			{
				__HAL_TIM_SetCompare(&htim16, TIM_CHANNEL_1, 60);
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
			}
			HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1);
			class_state = 4;
			GetSecd(); // 更新时间
			last_time = ral_time;
		}
		break;

5.5状态4

case 4:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);
			GetSecd(); // 更新时间
			if (ral_time - last_time > 6)
			{
				class_state = 5;
				Floor[p_run] > ral_floor ? ral_floor++ : ral_floor--;
				last_time = ral_time;
			}
			else
			{
				if (Floor[p_run] > ral_floor)
				{
					LedUP();
				}
				else
				{
					LedDown();
				}
			}
		}
		break;

5.6状态5

		case 5:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);

			if (Floor[p_run] == ral_floor)
			{
				Floor[p_run] = 0;
				p_run++;//指向下一个运行楼层
				class_state = 6;
				HAL_TIM_PWM_Stop(&htim16, TIM_CHANNEL_1);
				__HAL_TIM_SetCompare(&htim17, TIM_CHANNEL_1, 60);
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
				HAL_TIM_PWM_Start(&htim17, TIM_CHANNEL_1);//PWM&按键操作
				sprintf(text, "        %d", ral_floor);
				LCD_DisplayStringLine(Line5, (uint8_t *)text);
				HAL_Delay(300);
				LCD_ClearLine(Line5);
				HAL_Delay(300);
				LCD_DisplayStringLine(Line5, (uint8_t *)text);//楼层闪烁
				GetSecd(); // 更新时间
				last_time = ral_time;
			}
			else
			{
				class_state = 4;
			}
		}
			braek;

5.7状态6

case 6:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);

			GetSecd(); // 更新时间
			if (ral_time - last_time > 4)
			{
				Led -= (1 << (ral_floor - 1));
				LedDisp(~Led); // 灭灯
				class_state = 7;
				HAL_TIM_PWM_Stop(&htim17, TIM_CHANNEL_1);
				last_time = ral_time;
			}
			else
			{
				LedOpen();
			}
		}
		break;

5.8状态7

	case 7:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);

			GetSecd(); // 更新时间
			if (Floor[p_run] && p_run != 3)
			{
				class_state = 8;
				last_time = ral_time;
			}
			else
			{
				class_state = 0;
				p_arrdown = p_arrUp = p_run = 0;//全部数组指向0
			}
		}
		break;

5.9状态8

case 8:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);

			GetSecd(); // 更新时间
			if (ral_time - last_time > 2)
			{
				class_state = 1;
				HAL_TIM_PWM_Stop(&htim17, TIM_CHANNEL_1);
				last_time = ral_time;
			}
		}
		break;

6主程序

int main(void)
{
	/* USER CODE BEGIN 1 */

	/* USER CODE END 1 */

	/* MCU Configuration--------------------------------------------------------*/

	/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
	HAL_Init();

	/* USER CODE BEGIN Init */

	/* USER CODE END Init */

	/* Configure the system clock */
	SystemClock_Config();

	/* USER CODE BEGIN SysInit */

	/* USER CODE END SysInit */

	/* Initialize all configured peripherals */
	MX_GPIO_Init();
	MX_TIM4_Init();
	MX_TIM16_Init();
	MX_TIM17_Init();
	MX_RTC_Init();
	/* USER CODE BEGIN 2 */

	LedDisp(0x00);
	LCD_Init(); // LCD屏的初始化

	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);

	HAL_TIM_Base_Start_IT(&htim4); // 开启定时器时钟4

	HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1); // 开启PWM
	HAL_TIM_PWM_Start(&htim17, TIM_CHANNEL_1);

	ral_floor = 1;		  // 默认楼层为1
	GetSecd();			  // 得到时间
	last_time = ral_time; // 更新时间
	/* USER CODE END 2 */

	/* Infinite loop */
	/* USER CODE BEGIN WHILE */
	while (1)
	{
		/* USER CODE END WHILE */

		/* USER CODE BEGIN 3 */
		DispLcD(); // 更新lcd;
		switch (class_state)
		{
		case 0:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);
			GetSecd();											// 更新时间
			if (ral_time - last_time > 1 && (Up[0] || down[0])) // 当最后一次按键按键1s后并且有数据才会进入下一个阶段
			{
				class_state = 1;
				last_time = ral_time;
				arrCap();
			}
			else
			{
				Read_key();
			}
		}
		break;
		case 1:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);
			__HAL_TIM_SetCompare(&htim17, TIM_CHANNEL_1, 50);	  // 设置占空比50%
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); // 设置PA5低电平
			HAL_TIM_PWM_Start(&htim17, TIM_CHANNEL_1);			  // 开启PWM
			class_state = 2;
			GetSecd(); // 更新时间
			last_time = ral_time;
		}
		break;
		case 2:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);
			GetSecd(); // 更新时间
			if (ral_time - last_time > 4)
			{
				class_state = 3;
				HAL_TIM_PWM_Stop(&htim17, TIM_CHANNEL_1);//停止PWM
				last_time = ral_time;
			}
			else
			{
				LedClose();
			}
		}
		break;
		case 3:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);
			if (Floor[p_run] > ral_floor)//判断上升还是下降
			{
				__HAL_TIM_SetCompare(&htim16, TIM_CHANNEL_1, 80);
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
			}
			else
			{
				__HAL_TIM_SetCompare(&htim16, TIM_CHANNEL_1, 60);
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
			}
			HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1);
			class_state = 4;
			GetSecd(); // 更新时间
			last_time = ral_time;
		}
		break;

		case 4:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);
			GetSecd(); // 更新时间
			if (ral_time - last_time > 6)
			{
				class_state = 5;
				Floor[p_run] > ral_floor ? ral_floor++ : ral_floor--;
				last_time = ral_time;
			}
			else
			{
				if (Floor[p_run] > ral_floor)
				{
					LedUP();
				}
				else
				{
					LedDown();
				}
			}
		}
		break;
		case 5:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);

			if (Floor[p_run] == ral_floor)
			{
				Floor[p_run] = 0;
				p_run++;//指向下一个运行楼层
				class_state = 6;
				HAL_TIM_PWM_Stop(&htim16, TIM_CHANNEL_1);
				__HAL_TIM_SetCompare(&htim17, TIM_CHANNEL_1, 60);
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
				HAL_TIM_PWM_Start(&htim17, TIM_CHANNEL_1);//PWM&按键操作
				sprintf(text, "        %d", ral_floor);
				LCD_DisplayStringLine(Line5, (uint8_t *)text);
				HAL_Delay(300);
				LCD_ClearLine(Line5);
				HAL_Delay(300);
				LCD_DisplayStringLine(Line5, (uint8_t *)text);//楼层闪烁
				GetSecd(); // 更新时间
				last_time = ral_time;
			}
			else
			{
				class_state = 4;
			}
		}
			braek;
		case 6:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);

			GetSecd(); // 更新时间
			if (ral_time - last_time > 4)
			{
				Led -= (1 << (ral_floor - 1));
				LedDisp(~Led); // 灭灯
				class_state = 7;
				HAL_TIM_PWM_Stop(&htim17, TIM_CHANNEL_1);
				last_time = ral_time;
			}
			else
			{
				LedOpen();
			}
		}
		break;
		case 7:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);

			GetSecd(); // 更新时间
			if (Floor[p_run] && p_run != 3)
			{
				class_state = 8;
				last_time = ral_time;
			}
			else
			{
				class_state = 0;
				p_arrdown = p_arrUp = p_run = 0;//全部数组指向0
			}
		}
		break;
		case 8:
		{
			sprintf(text, "        %d", class_state);
			LCD_DisplayStringLine(Line2, (uint8_t *)text);

			GetSecd(); // 更新时间
			if (ral_time - last_time > 2)
			{
				class_state = 1;
				HAL_TIM_PWM_Stop(&htim17, TIM_CHANNEL_1);
				last_time = ral_time;
			}
		}
		break;
		}
		sprintf(text, " %d %d %d", Floor[0], Floor[1], Floor[2]);
		LCD_DisplayStringLine(Line1, (uint8_t *)text);
	}
	/* USER CODE END 3 */
}

总结

本人新手,只学过江科大32标准库,HAL没有系统学过,如有错误欢迎大佬指出!文章的主要目的也是记录自己的学习过程。

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值