srkxrolz 发表于 昨天 04:34

第七课:定时器和中断Stc-isp中可以生成定时器时钟和中断函数例子中使用定时器0 生成3秒一次的中断调用,在中断处理中控制LEd状态中断程序优先级高于while可以比较准确的实现程序定时执行,但是中断程序中尽量不要执行耗时太长的程序,一般只作为标志的更改,具体执行可以交给while进行        TM0PS = 0x1E;                        //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )        AUXR &= 0x7F;                        //定时器时钟12T模式        TMOD &= 0xF0;                        //设置定时器模式        TL0 = 0xFC;                                //设置定时初始值        TH0 = 0x03;                                //设置定时初始值        TF0 = 0;                                //清除TF0标志        TR0 = 1;                                //定时器0开始计时        ET0 = 1;                                //使能定时器0中断定时器的结构 系统时钟sysclk时钟通过TM0PS设置分频(tm0ps的值+1:如果tmops设位0则表示不分频,但是实际计算的时需要为1,因此预分频会自动加1),然后得到的时钟还可以进行12分频或者1分频,然后获得的时钟通过GATE选择是时钟脉冲技术还是外部脉冲计数,计数器中由两套寄存器完成TH0和TL0可以组成一个16位的计数器,RL_TH0和RL_TL0是他们的影子寄存器,他们有同一个地址,这里具体过程需要看手册视频并没有详细讲解他们的工作过程,在这里反正就是用作自动重装载,当计数器从初始值计数到溢出则产生一个中断,这时候如果TF0中断标志位置1就调用中断函数,这个溢出信号还可以通过因gpio输出,但是这就需要T0clk允许位控制了 函数定义:返回值类型函数名 (参数){函数体;Return 返回值;} #include "ai8051u.h"#include "ai_usb.h"bit p32_status = 0;                                // 初始化状态bit p33_status = 0;                                // 初始化状态unsigned long systick_cont = 0; // 系统滴答计数器 void Delay1000ms(void) //@24.000MHz{        unsigned long edata i;         _nop_();        _nop_();        i = 5999998UL;        while (i)                i--;} void Timer0_Isr(void) interrupt 1{        P20 = ~P20;                // 切换P20状态        systick_cont++; // 增加系统滴答计数器        // printf_usb("systick_cont: %d\n", systick_cont);} void Timer0_Init(void)                //1秒@24.000MHz{        TM0PS = 0x1E;                        //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )        AUXR &= 0x7F;                        //定时器时钟12T模式        TMOD &= 0xF0;                        //设置定时器模式        TL0 = 0xFC;                                //设置定时初始值        TH0 = 0x03;                                //设置定时初始值        TF0 = 0;                                //清除TF0标志        TR0 = 1;                                //定时器0开始计时        ET0 = 1;                                //使能定时器0中断} void main(){        WTST = 0;// 设置程序指令延时参数        EAXFR = 1; // 设置EAXFR位为1,允许访问扩展寄存器        CKCON = 0; // 提高访问xram速度         P2M0 = 0x00;   // 设置P2口为通用I/O口        P2M1 = 0x00;   // 设置P2口为通用I/O口        P2 = 0x0f;           // 设置P2口初始状态        Timer0_Init(); // 初始化定时器0        usb_init();           // 初始化USB        EA = 1;                   // 允许总中断         while (1)        {                Delay1000ms(); // 延时1秒                P21 = ~P21;           // 切换P21状态        printf("systick:%dP20: %d   P21: %d\n", systick_cont, P20, P21); // 打印P21和P20状态                if (bUsbOutReady) // 检查Usb是否准备好                {                        USB_SendData(UsbOutBuffer, OutNumber);//                        printf_usb("1. Read Num:%d\n", OutNumber);//                        printf_usb("2. Read Num:%d\n", OutNumber);//                        printf_usb("3. Read Num:%d\n", OutNumber);//                        printf_usb("4. Read Num:%d\n", OutNumber);                         usb_OUT_done();                }        }}

red枫叶 发表于 昨天 07:32

好好学习

laohu_zhou 发表于 昨天 08:15

继续打卡学习。

无锡科技工场 发表于 昨天 09:00

{:4_196:}{:4_196:}

白水大虾2016 发表于 昨天 20:22

今天还是第九集 数码管

laohu_zhou 发表于 8 小时前

打卡学习

fs_ajin 发表于 8 小时前

今日打卡

srkxrolz 发表于 6 小时前

打卡
第八课:systick与task周期调度
结构体
typedef struct
{
    u8 Run;
    u16 TIMECont;
    u16 TRITime;
    void (*TaskFunc)(void);
} Task;
用一个结构体管理任务信息
在系统中准备一个tasklist并确定最大长度(因为涉及到内存分配问题这里使用固定任务长度,相当于是预先确定task数组的内存大小)
#define TASK_MAX 10
Task TaskList={0};
初始化tasklist这个可以在main中调用一次,当然不调用也没什么问题
void TASK_Init(void)
{
    u8 i;
    for (i = 0; i < TASK_MAX; i++)
    {
        TaskList.Run = 0;
        TaskList.TIMECont = 0;
        TaskList.TRITime = 0;
        TaskList.TaskFunc = NULL;
    }
}
暴露三个函数用于添加,执行,运行状态管理
void task_add(u8 index, void (*taskFunc)(void), u16 triTime)
{
    if (index < TASK_MAX)
    {
        TaskList.Run = 1;
        TaskList.TaskFunc = taskFunc;
        TaskList.TRITime = triTime;
    }
}
void task_run(void)
{
    u8 i;
    for (i = 0; i < TASK_MAX; i++)
    {
    //    if (TaskList.TRITime!=0)
    //    {
    //     printf("Run:task[%d]: tr:%d tm:%d RUN:%d \r\n",i,TaskList.TRITime,TaskList.TIMECont,TaskList.Run);
    //    }
       

        if (TaskList.Run==1)
        {
             printf("Run:task[%d]: tr:%d tm:%d RUN:%d \r\n",i,TaskList.TRITime,TaskList.TIMECont,TaskList.Run);
            if (TaskList.TaskFunc != NULL)
            {
                TaskList.TaskFunc();
                 TaskList.Run=0;
            }
        }
    }
}
void task_timer(void)
{
    u8 i;
    for (i = 0; i < TASK_MAX; i++)
    {
   
        if (TaskList.Run == 0 && TaskList.TRITime != 0)
        {
            TaskList.TIMECont++;
            if (TaskList.TIMECont >= TaskList.TRITime)
            {
                TaskList.TIMECont=0;
                TaskList.Run = 1;
            }
                 
        }
    }
}


然后将task_run在main中的while里面循环调用即可,
状态控制程序库丢到while运行 或者放到定时器中断里面精确控制

乐高 发表于 27 分钟前

终于等到更新了
页: 154 155 156 157 158 159 160 161 162 163 [164]
查看完整版本: 《8051U深度入门到32位51大型实战视频》,【免费 + 包邮 送】实验箱@Ai8051U,100万套