zoukankan      html  css  js  c++  java
  • 课后实践之嵌入式基础20155314

    课后实践之嵌入式基础

    任务详情

    在作业本上完成附图作业,要认真看题目要求。

    提交作业截图

    作弊本学期成绩清零(有雷同的,不管是给别人传答案,还是找别人要答案都清零)

    预备知识

    嵌入式C语言——嵌入式系统中的数据打包

    1. 地址的定义

      #define DATA_Addr 0x0C00000
      #define DATA *(volatile int *)(DATA_Addr)
      DATA = 0x1234;
      
    2. 提取位

      • 提取Minutes:

        分析:由于Seconds占5位,因此需要先右移5位将Minutes的最低位与位0对齐,再与(&)上3F(0000 0000 0011 1111)即可将6-15位全部清0从而取出Minutes的全部6位

        假设Hours的5位全为A,Minutes的6位全为B,则:

          	00000 00000 111111
          &	????? AAAAA BBBBBB
          =	00000 00000 BBBBBB 
        
      • 提取Hours:
        分析:由于Seconds占5位,Minutes占6位(共占11位),因此需要先右移11位将Hours的最低位与位0对齐,再与(&)上1F(0000 0000 0001 1111)即可将5-15位全部清0从而取出Hours的全部5位

        假设Hours的5位全为C,Minutes的6位全为B,则:

          	00000 000000 11111
          &	????? ?????? CCCCC
          =	00000 000000 CCCCC 
        
      • 提取Seconds:
        分析:由于Seconds占低5位,因此无需右移最低位即与位0对齐,只需与(&)上1F(0000 0000 0001 1111)即可将5-15位全部清0从而取出Seconds的全部5位

        假设Seconds的5位全为A,Minutes的6位全为B,Hours的5位全为C,则:

          	00000 000000 11111
          &	CCCCC BBBBBB AAAAA
          =	00000 000000 AAAAA 
        
    3. 插入位(插入Minutes)

    关于volatile关键字

    • volatile关键字的官方说明

      Indicates that a variable can be changed by a background routine.

      Keyword volatile is an extreme opposite of const. It indicates that a variable may be changed in a way which is absolutely unpredictable by analysing the normal program flow (for example, a variable which may be changed by an interrupt handler). This keyword uses the following syntax: volatile data-definition;

      Every reference to the variable will reload the contents from memory rather than take advantage of situations where a copy can be in a register.

      大概意思是说,一个变量如果用volatile修饰,则会从内存中重新装载其内容,而不是直接从寄存器中拷贝其内容

    • 使用volatile关键字的目的

      • 让对volatile变量的存取不能缓存到寄存器,每次使用时需要重新存取
    • 嵌入式系统编程,要求程序员能够利用C语言访问固定的内存地址,根据C语言的语法规则,这个表示地址的量应该是指针类型。以上面的地址定义为例:

      #define DATA_Addr 0x0C00000
      #define DATA *(volatile int *)(DATA_Addr)
      DATA = 0x1234;
      

      意思是初始化内存地址0x0C00000的值为0x1234,这里的DATA_Addr就是内存地址0x0C00000。则在知道要访问的内存地址后,执行以下两步:

      1. 把它强制转换为指针类型(int *)(DATA_Addr)
        则地址0x0C00000强制转换为指向int类型
      2. 对指针变量解引用*(volatile int *)(DATA_Addr),就能操作指针所指向的地址的内容了

      注:把#define宏中的参数用括号括起来,这是一个很好的习惯。不用括号易导致出错,如本题的时间存放在基址+2的寄存器中,应写成#define TIME *(volatile int *)(Time_Addr+2),稍不注意就容易写成#define TIME *(volatile int *) Time_Addr+2导致错误!

    最终代码

    #define Time_Addr 0xFFFFC0000 //实时钟芯片的IO映像基址是OxFFFFC0000
    #define TIME *(volatile int *)(Time_Addr+2) //时间存放在基址+2的寄存器中
    void SetHours(int hours) //插入Hours
    {
    	int oldtime=TIME;
    	int newtime;
    	newtime=oldtime&~(0x1F<<11);
    	newtime|=(hours&0x1F)<<11;
    	TIME=newtime;
    
    }
    int getHours() //取出Hours
    {
    	int time=TIME;
    	return (time>>11)&0x1F;
    }
    
    void SetMinutes(int minutes) //插入Minutes
    {
    	int oldtime=TIME;
    	int newtime;
    	newtime=oldtime&~(0x3F<<5);
    	newtime|=(minutes&0x3F)<<5;
    	TIME=newtime;
    
    }
    int getMinutes() //取出Minutes
    {
    	int time=TIME;
    	return (time>>5)&0x3F;
    }
    
    void SetSeconds(int seconds) //插入Seconds
    {
    	int oldtime=TIME;
    	int newtime;
    	newtime=oldtime&~0x1F;
    	newtime|=(seconds/2)&0x1F;
    	TIME=newtime;
    
    }
    int getSeconds() //取出Seconds
    {
    	int time=TIME;
    	return (time&0x1F)*2; //此处不考虑Seconds除2带来的误差,因此直接乘2
    }
    

    参考资料

  • 相关阅读:
    Java的代理proxy机制
    Java 编译器 javac 笔记:javac API、注解处理 API 与 Lombok 原理
    Java 运行时获取方法参数名
    python 之 list 和 dict 置空
    Python 模块(Module)调用
    Python 模块(Module)及包
    Mybatis中进行批量更新(updateBatch)
    可持久化线段树+主席树+动态主席树
    无向图的割点与割边
    [NOIP2016] 愤怒的小鸟 题解
  • 原文地址:https://www.cnblogs.com/crazymosquito/p/8185803.html
Copyright © 2011-2022 走看看