找回密码
 立即注册
楼主: 冰封眸

《8051U深度入门到32位51大型实战视频》学习打卡 | 已送

[复制链接]
  • 打卡等级:偶尔看看II
  • 打卡总天数:24
  • 最近打卡:2025-02-25 15:40:39
已绑定手机

1

主题

9

回帖

143

积分

注册会员

积分
143
发表于 2024-12-20 22:12:20 | 显示全部楼层

第六集 课后作业

题目:按一下亮一个灯,再按一下亮两颗灯,直到全亮

实验说明

按P32亮一颗LED灯,直至全亮;再加了一个功能,按P33灭一颗LED灯直至全灭

代码实现

按键代码

key.h

#ifndef __KEY_H
#define __KEY_H


/* Includes ------------------------------------------------------------------*/
#include <AI8051U.H>
#include "delay.h"

#define     SW_2        P32         /* 定义SW2的控制引脚 */
#define     SW_3        P33         /* 定义SW3的控制引脚 */

#define     UP          1           /* 按键抬起 */
#define     DOWN        0           /* 按键按下 */

#define     SW2         2           /* 定义SW2键值 */
#define     SW3         3           /* 定义SW3键值 */

void key_init();
unsigned char scan_key();
#endif

key.c

#include "key.h"

void key_init()
{
    P3M0 = 0; P3M1 = 0;             /* 设置P3端口为准双向 */
}

/**
 * @brief       扫描哪个按键被按下
 * @param       无
 * @retval      被按下键的键值
 */
unsigned char scan_key()
{
    unsigned char key_value = 0;
    if (SW_2 == DOWN)
    {
        Delay_ms(10);               /* 延时消抖 */
        if(SW_2 == DOWN)
        {
            while (SW_2 == DOWN)
                ;                   /* 等待按键抬起 */
            key_value = SW2;
        }
    } 
    else if (SW_3 == DOWN) 
    {
        Delay_ms(10);               /* 延时消抖 */
        if(SW_3 == DOWN)
        {
            while (SW_3 == DOWN)
                ;                   /* 等待按键抬起 */
            key_value = SW3;
        }
    }
  
    return key_value;
}

LED代码

led.h

#ifndef __LED_H
#define __LED_H

/* Includes ------------------------------------------------------------------*/
#include <AI8051U.H>

#define         LED_PORT        P0              // 定义LED端口
#define         LED_SW          P40             // 定义LED组开关
#define         LED0            P00             // 定义LED0控制引脚

#define         ON              0               // LED点亮
#define         OFF             1               // LED熄灭

void LED_Init();
#endif

led.c

#include "led.h"

void LED_Init()
{
    P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    LED_PORT = 0xFF;
    LED_SW = 0;
}

main函数实现

main.c

#include "led.h"
#include "key.h"

void main()
{
    unsigned char key_value = 0;
  
    WTST = 0;           // 设置程序指令延时参数
    EAXFR = 1;          // 扩展寄存器(XFR)访问使能
    CKCON= 0;           // 提高访问XRAM速度

    LED_Init();
    key_init();
    while(1)
    {
        key_value = scan_key();
        if (key_value == SW2)
        {
            LED_PORT <<= 1;                        // 实现亮灯
        }
        else if (key_value == SW3)
        {
            LED_PORT = (LED_PORT >> 1) | 0x80;    // 实现灭灯
        }
    }
}

实验现象

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看II
  • 打卡总天数:24
  • 最近打卡:2025-02-25 15:40:39
已绑定手机

1

主题

9

回帖

143

积分

注册会员

积分
143
发表于 2024-12-29 23:31:49 | 显示全部楼层

第八集 定时器周期性调度任务

数组

  1. 定义
    类型 名称[长度] = {数值};
  2. 使用
    赋值:名称[索引] = 数值;
    image.png

文件的创建(.c和.h)

创建程序文件三步,把硬件需要的初始化弄到一个config.c
新建文件并保存
添加到工程
添加引用路径

一般一个.c和一个.h文件执行一个外设或者一个任务或功能。这样可以让代码看起来简洁明了

以下是通过定时器,实现LED0,LED1和LED2以0.5S 1S 2S的频率亮灭
task.h

#ifndef __TASK_H_
#define __TASK_H_

/* Includes ------------------------------------------------------------------*/
#include "type_def.h"
#include ".\led\led.h"

//========================================================================
//                               本地变量声明
//========================================================================
typedef struct 
{
	u8 Run;               //任务状态:Run/Stop
	u16 TIMCount;         //定时计数器
	u16 TRITime;          //重载计数器
	void (*TaskHook) (void); //任务函数
} TASK_COMPONENTS;   

//========================================================================
//                             外部函数和变量声明
//========================================================================
void Task_Marks_Handler_Callback(void);
void Task_Pro_Handler_Callback(void);

#endif

task.c

#include "task.h"

//========================================================================
//                               本地变量声明
//========================================================================

static TASK_COMPONENTS Task_Comps[]=
{
    //状态  计数  周期  函数
    {0, 500,    500,    LED0_blink},          /* task 1 Period: 500ms */
    {0, 1000,   1000,   LED1_blink},          /* task 2 Period: 1000ms */
    {0, 2000,   2000,   LED2_blink}          /* task 3 Period: 2000ms */
};

u8 Tasks_Max = sizeof(Task_Comps)/sizeof(Task_Comps[0]);

//========================================================================
// 函数: Task_Handler_Callback
// 描述: 任务标记回调函数.
// 参数: None.
// 返回: None.
// 版本: V1.0,
//========================================================================
void Task_Marks_Handler_Callback(void)
{
    u8 i;
    for(i=0; i<Tasks_Max; i++)
    {
        if(Task_Comps[i].TIMCount)      /* If the time is not 0 */
        {
            Task_Comps[i].TIMCount--;   /* Time counter decrement */
            if(Task_Comps[i].TIMCount == 0) /* If time arrives */
            {
                /*Resume the timer value and try again */
                Task_Comps[i].TIMCount = Task_Comps[i].TRITime;  
                Task_Comps[i].Run = 1;      /* The task can be run */
            }
        }
    }
}

//========================================================================
// 函数: Task_Pro_Handler_Callback
// 描述: 任务处理回调函数.
// 参数: None.
// 返回: None.
// 版本: V1.0
//========================================================================
void Task_Pro_Handler_Callback(void)
{
    u8 i;
    for(i=0; i<Tasks_Max; i++)
    {
        if(Task_Comps[i].Run) /* If task can be run */
        {
            Task_Comps[i].Run = 0;      /* Flag clear 0 */
            Task_Comps[i].TaskHook();   /* Run task */
        }
    }
}

timer.h

#ifndef __TiMER_H
#define __TIMER_H

#include "sys_config.h"
#include <AI8051U.h>
#include "type_def.h"
#include "task.h"

void timer_init(void);

#endif

timer.c

#include "timer.h"

/**
 * @brief      定时器配置 
 * @param       无
 * @retval      无
 */
void timer_init(void)
{
    AUXR = 0x80;    //Timer0 1T模式, 16位自动重装计时器, 
    TH0 = (u8)(Timer0_Reload / 256);
    TL0 = (u8)(Timer0_Reload % 256);
    ET0 = 1;        //Timer0 中断使能
    TR0 = 1;        //Tiner0 运行
}

void Timer0_ISR_Handler (void) interrupt TMR0_VECTOR        //进中断时已经清除标志
{
    Task_Marks_Handler_Callback();    //任务标记回调函数
}

main.c

#include "sys_init.h"
//#include "sys_config.h"
#include "task.h"

void main()
{
    SYS_Init();
    while(1)
    {
        Task_Pro_Handler_Callback();
    }
}

实现效果如图

回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-6 20:49 , Processed in 0.107910 second(s), 54 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表