6.28

来源:互联网 发布:学校机房教学软件 编辑:程序博客网 时间:2024/05/21 20:22
《6.28》
(1).MRS/MSR与PRIMASK之间的关系:
    1.PRIMASK的作用:用来除能NMI和硬fault之外的所有异常,相当于将优先级设置成0.其代码如下:
      MOV  R0,#1        //写1是关闭中断
      MSR  PRIMASK,R0
 
      MOV  R0,#0        //写0是开启中断
      MSR  PRIMASK,R0            
        
    2.MRS命令的作用:
      一般情况下,对于MRS为CPRS/SPRS传到寄存器。
                   MSR为寄存器传到CPRS/SPRS.
      CPRS当前程序寄存器的作用:
       该寄存器前部分的几个位,表示是否相等、进位、溢出,中间保留,后部分为I、F、       


M4/M3/M2/M1
       重点介绍:I、F第7、6两个位为中断和快速中断位,可以通过对CPRS的写1设置来禁止中断。


       cpu上电复位需要关闭快速中断和中断,代码如下:
       方法一:
     MRS  R0,CPRS      //将CPRS的值读到R0中
         AND  R0,R0,&0x00 //将R0清零
         ORR  R0, R0, &0xC0 //R0置位,第6、7位写1禁止快速和中断位
         MSR  CPRS,R0       //R0的值写入到CPRS中
            方法二:
     CPSID I            //关闭普通中断
     
    3.那么MRS与PRIMASK的关系:
      OS_CPU_SR_SAVE
MRS   R0,PRIMASK
      解释:


(2)typedef的新理解:  
   typedef 不仅可以对于typedef struct A{}a;可以用a取代struct A test的定义,a test有等同含义
           同时它可以定义整形数值typedef unsigned int OS_STK;用OS_STK *stk直接定义变量。






(3)OS_CPU.h与OS_CPU_A.a的联系:
      其中.h中定义数据的类型和几个函数,然后这几个重要函数就是在.a中实现的。
  OS_CPU_C.c的作用:
      .c中定义了栈初始化和cpu和app的勾联函数。
 
void OSCtxSw(void)   //用户任务切换函数
void OSIntCtxSw(void) //中断任务切换函数
void OSStartHighRdy(void) //在操作系统第一次启动的时候调用的任务切换
void OS_CPU_PendSVHandler(void) //用户中断服务程序
void OS_CPU_SysTickHandler(void)//系统定时器中断
void OS_CPU_SysTickInit(void)   //系统Systick定时器初始化
INT32U OS_CPU_SysTickCLKFreq(void) //返回SysTick定时器的时钟频率


   SVC的作用:
   SVC(系统调用)->SVC指令->SVC异常服务例程解析->调用相应的服务函数。
   PendSV的作用:
   不像SVC异常一样必须执行,没执行就会上访成硬fault,应用程序执行SVC时都希望立即执行。
   而PendSV则可以像普通的中断一样悬起(不像SVC会上访成硬fault)。
   悬起的做法:手工向PendSV寄存器中写1。悬起后,如果优先级不够高,则将缓期等待执行。




《6.29》
1.IIC的Wait_ACK和产生ACK的区别:
   (1)IIC_Wait_ACK是作为主机时,等待从机给予回复。
   (2)IIC_ACK是作为从机时,给予对方回复。
    IIC_Wait_ACK代码分析
    IIC发送时,由于需要对方的应答信号,所以在初始化时SCL=1、SDA=1。满足它们在SCL为高电平
的条件下,SDA等待被从机拉低。而检测是否拉低,通过#define Read_SDA PBin(9)定义的SDA输入检测

。if(Read_SDA) { count++;  if(count>255) return 1;} 改行代码的含义即:等待拉低但有时间限制,超时则

不等待,然后SCL = 0.

    IIC_ACK代码分析 
    SCL=0;delay;SDA = 0;delay;SCL=0;delay;SCL=0;delay 原则是在SCL的高电平期间,保持低电平。
 
2.应答信号在AT24c02中的读写数据运用:
    ATC02在主机进行读数据,最后不必要产生应答信号;但主机进行写,最后必须产生应答信号 ,告
诉主机写完成,再产生停止信号。
3.IIC写字符到EEPROM中,读EEPROM到液晶屏的过程:
    在写入字符到EEPROM中,实际上写入的是一个8位的2进制数,然后读出来的也是8位二进制数,调用
液晶显示字符函数,该函数对于这个8位的值,实际上对应着字符库中[num][]=的偏移量,通过这个找到
了对应字符。


4.各种通信的区别:
  (1).串口实验方式是支持半双工单线通讯。
  (2).IIC是双线式串行总线。
  (3).SPI是高速单工/全双工的同步的通信方式。 SPI 接口主要应用在 EEPROM, FLASH,实时时钟, 
AD 转换器,还有数字信号处理器和数字信号解码器之间。(例:stm32的W25Q128、慧静电子的SD卡实验
).
  (4).I2S支持全双工和半双工。
  (5)SDIO为4位模式,最高通信可达48Mhz(分频器旁路时),最高每秒可传输数据24M字节。STM32F4的
SDIO控制器支持多媒体(MMC卡)、SD存储卡、SD I/O卡和CE-ATA设备等。(例:stm32的SD卡实验)
  注意:SD卡支持SPI和SDIO两种驱动方式。
5.关于ECC校验码:
  SD的数据通过Error Correction Code(ECC)进行保护。在写sector时生成ECC,在读sector时检验ECC。
如果发现错误,在传输前纠正。


6.SPI中SPI1->CR1 |=1<<6和SPI1_ReadWriteByte(0xff)的区别:
  前者是SPI设备使能,后者是启动传输。
 
7.W25Q128中对应的QPI即mod 3(即空闲时低电平)。
  W25Q128支持标准的串口外设接口SPI、Dual/Quad I/O SPI和2-clock时钟指令周期的Qual指令:
  SINGLE SPI操作模式,即Standard SPI。DI引脚用来写指令、数据、地址到设备在上升沿的时候。
                                      DO引脚用来读出数据和状态在下降沿的时候。
      其中mode0和3的不同仅仅是空闲时的电平状态不同而已。
  Dual SPI操作使用指令"Fast Read Dual Output(3Bh)"和"Fast Read Dual I/O(BBh)".这些指令允许


              数据以4-6倍速度从普通串行Flash中读出。
  Quad SPI操作使用指令"Fadt Read Quad Output(6Bh)"、"Fast Read Quad I/O(EBh)"、"Word Read
                       Quad I/O(E7h)"、"Octal Word Reset Quad I/O(E3h)"。这些指令允许数据
                       以4-6倍速度从普通串行Flash中读出。
  QPI操作使用指令"Enter QPI(38h)"使设备从Standard/Dual/Quad SPI mode到QPI.
      注意:(1)刚上电或者使用软件复位"Reset(99h)"指令,系统将处于Standard/Dual/Quad SPI     


           mode。
            (2)为了使能QPI指令,在状态寄存器-2的non-volatile Quad Enable位(QE)需要被置1。
  Hold Funtion引脚仅在Standard SPI和Dual SPI模式下可以使用,而在Dual和Quad模式下不能。原因  
                       后者两种模式要征用D2/D3,即WP、HOLD/Reset位。那么正好当状态寄存器-2
                       的Quad Enable位置时,HOLD/Reset位变成D3。当状态寄存器-2的Quad Enable
                       位为0时,则端口功能为HOLD/Reset。与注意(2)对应起来。
  Software Reset&Hardware /Reset:1.通过软件序列来进行初始化,无论是SPI或者QPI都可以。
                                                                   连续命令为:Enable Reset(66H)&Reset(99H).
                                   2.硬件上配置Status Register-3的HOLD/RST位,如果HLOD/RST为
                                                                  0(出厂默认),则为HOLD功能。如果HOLD/RST为1,则配置为     
                                                                 硬件复位Reset功能。如果QE置1,就根本不存在HOLD/RESET功能   。 


8.W25Q128的写数据函数的过程:

         remain=NumByteToWrite来判定是否要进行写满不够,另一页的读写。
         同时在之前会用W25Q128_BUF[4096]将所有sector扇区的内容读出后,再对扇区要写入的部分

进行校验,即在要写入的部分(此时不管remain和NumByteToWrite是否相等)存在不等于OXFF的

        部分,就要进行擦除操作,再进行W25Q128_Write_NoCheck()写操作,如果校验不存在不等于  

         0XFF的部分,则可以直接进行写操作W25Q128_Write_NoCheck(),则不需要对flash响应的扇区 

         sector(4k)进行擦除操作。

重要的分析代码如下:

u8 W25QXX_BUFFER[4096];
void W25QXX_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)
{   
 u16 i;
 u32 secpos;
 u16 secoff;
 u16 secremain;
 u8 *W25QXX_BUF;
 W25QXX_BUF=W25QXX_BUFFER;
 secpos = WriteAddr/4096;            //扇区地址
 secoff = WriteAddr%4096;           //在扇区的偏移地址
 secremain = 4096-secoff;           //扇区内的剩余空间大小
 if(NumByteToWrite<=secremain) secremain = NumByteToWrite; 
 while(1)
 {
W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//读出整个扇区
 for(i=0;i<secremain;i++)           //如果在secoff-secoff+remain的范围内存在不等于0XFF的
 {                                                     //则进行下面的擦除操作 
                                        //此时secremain不一定等于NumByteToWrite的值
if(W25QXX_BUF[secoff+i]!=0xff) break;
}
if(i<secremain)     //如果不存在不等于0xff的值的话,secremain=1
   {
   W25QXX_Erase_Sector(WriteAddr);   //之前扇区内容已读取,所以现在可以将其擦除
                                    for(i=0;i<secremain;i++)          //此时的remain要么等于NumByteToWrite,要么等于4096
            W25QXX_BUF[secoff+i]=pBuffer[i];
             W25QXX_Write_NoCheck(W25Q128_BUF,WriteAddr,secremain);
}else W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);     //由于没有在校验不对的情况擦除
               //所以可以直接将pBuffer写入到sector

       //而不需要用到W25QXX_BUF[ ]来进行擦除过渡

                        if(NumByteToWrite==secremain)

                        {

secpos ++;                       //扇区地址增1

secoff = 0;                        //偏移位置为0

  pBuffer += secremain;  //指针偏移

                               WriteAddr += secremain; //写地址偏移

   NumByteToWrite -= 4096;//字节数递减

                               if(NumByteToWrite>4096)secremain=4096;//下一个扇区还是写不完
else secremain=NumByteToWrite;//下一个扇区可以写完了

}
}                                                                 
}

0 0
原创粉丝点击