基于STM32+SD储存RS485传感器数据

   本文章基于上篇STM3传感器数据采集(基于STM32 RS485传感器数据采集(参考正点原子部分代码)_stm32用rs485代码_做个有理想的程序员的博客-CSDN博客)和原子哥SD储存数据。

如何将传感器的数据储存SD卡呢?

一、需要准备的硬件如下:

开发板、SD、传感器、电源、USB、读卡器(可以读取SD卡采集的数据,以便观察)

二、需要准备的知识

1、数据串口发送与接收  

void uart_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
     
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);    //使能USART1,GPIOA时钟
  
    //USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
   
  //USART1_RX      GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置

    USART_InitStructure.USART_BaudRate = bound;//串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;    //收发模式

  USART_Init(USART1, &USART_InitStructure); //初始化串口1
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART1, ENABLE);                    //使能串口1 

}

void USART1_IRQHandler(void)                    //串口1中断服务程序
    {
    u8 Res;
#if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
    OSIntEnter();    
#endif
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
        {
        Res =USART_ReceiveData(USART1);    //读取接收到的数据
        
        if((USART_RX_STA&0x8000)==0)//接收未完成
            {
            if(USART_RX_STA&0x4000)//接收到了0x0d
                {
                if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
                else USART_RX_STA|=0x8000;    //接收完成了 
                }
            else //还没收到0X0D
                {    
                if(Res==0x0d)USART_RX_STA|=0x4000;
                else
                    {
                    USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
                    USART_RX_STA++;
                    if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收      
                    }         
                }
            }            
     } 
#if SYSTEM_SUPPORT_OS     //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
    OSIntExit();                                               
#endif
} 
#endif  

2、传感器数据采集(上篇文章已经细讲)

3、学习SD卡如何接收和响应主机(CMD命令)

SD_Error SD_Init(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef  GPIO_InitStructure;
    
    u8 clkdiv=0;
    SD_Error errorstatus=SD_OK;     
  
    //SDIO IO口初始化

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,ENABLE);//使能PORTC,PORTD时钟
    
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_SDIO|RCC_AHBPeriph_DMA2,ENABLE);//使能SDIO,DMA2时钟     
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12;    //PC.8~12 复用输出
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;          //复用推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //IO口速度为50MHz
  GPIO_Init(GPIOC, &GPIO_InitStructure);                     //根据设定参数初始化PC.8~12 
 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;    //PD2 复用输出
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;          //复用推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //IO口速度为50MHz
  GPIO_Init(GPIOD, &GPIO_InitStructure);                     //根据设定参数初始化PD2

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;    //PD7 上拉输入
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;          //复用推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //IO口速度为50MHz
  GPIO_Init(GPIOD, &GPIO_InitStructure);                     //根据设定参数初始化PD7
 
     //SDIO外设寄存器设置为默认值                       
    SDIO_DeInit();
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
    NVIC_InitStructure.NVIC_IRQChannel = SDIO_IRQn;            //SDIO中断配置
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;    //抢占优先级0 
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;                    //子优先级0 
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                //使能外部中断通道
  NVIC_Init(&NVIC_InitStructure);        //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

  errorstatus=SD_PowerON();            //SD卡上电

     if(errorstatus==SD_OK)
        errorstatus=SD_InitializeCards();            //初始化SD卡    
    
  if(errorstatus==SD_OK)
        errorstatus=SD_GetCardInfo(&SDCardInfo);    //获取卡信息
    
     if(errorstatus==SD_OK)
        errorstatus=SD_SelectDeselect((u32)(SDCardInfo.RCA<<16));//选中SD卡
    
  if(errorstatus==SD_OK)
        errorstatus=SD_EnableWideBusOperation(1);    //4位宽度,如果是MMC卡,则不能用4位模式 
    
  if((errorstatus==SD_OK)||(SDIO_MULTIMEDIA_CARD==CardType))
    {              
        if(SDCardInfo.CardType==SDIO_STD_CAPACITY_SD_CARD_V1_1||SDCardInfo.CardType==SDIO_STD_CAPACITY_SD_CARD_V2_0)
        {
            clkdiv=SDIO_TRANSFER_CLK_DIV+6;    //V1.1/V2.0卡,设置最高72/12=6Mhz
        }else clkdiv=SDIO_TRANSFER_CLK_DIV;    //SDHC等其他卡,设置最高72/6=12Mhz
        SDIO_Clock_Set(clkdiv);                //设置时钟频率,SDIO时钟计算公式:SDIO_CK时钟=SDIOCLK/[clkdiv+2];其中,SDIOCLK固定为48Mhz 
        //errorstatus=SD_SetDeviceMode(SD_DMA_MODE);    //设置为DMA模式
        errorstatus=SD_SetDeviceMode(SD_POLLING_MODE);    //设置为查询模式
     }
    return errorstatus;         
}
//SDIO时钟初始化设置
//clkdiv:时钟分频系数
//CK时钟=SDIOCLK/[clkdiv+2];(SDIOCLK时钟固定为48Mhz)
void SDIO_Clock_Set(u8 clkdiv)
{
    u32 tmpreg=SDIO->CLKCR; 
  tmpreg&=0XFFFFFF00; 
     tmpreg|=clkdiv;   
    SDIO->CLKCR=tmpreg;
} 
 
//卡上电
//查询所有SDIO接口上的卡设备,并查询其电压和配置时钟
//返回值:错误代码;(0,无错误)
SD_Error SD_PowerON(void)
{
     u8 i=0;
    SD_Error errorstatus=SD_OK;
    u32 response=0,count=0,validvoltage=0;
    u32 SDType=SD_STD_CAPACITY;
 
    /*初始化时的时钟不能大于400KHz*/ 
  SDIO_InitStructure.SDIO_ClockDiv = SDIO_INIT_CLK_DIV;    /* HCLK = 72MHz, SDIOCLK = 72MHz, SDIO_CK = HCLK/(178 + 2) = 400 KHz */
  SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;
  SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;  //不使用bypass模式,直接用HCLK进行分频得到SDIO_CK
  SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;    // 空闲时不关闭时钟电源
  SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;                     //1位数据线
  SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;//硬件流
  SDIO_Init(&SDIO_InitStructure);
 
    SDIO_SetPowerState(SDIO_PowerState_ON);    //上电状态,开启卡时钟
       
    SDIO_ClockCmd(ENABLE);//SDIOCK使能 
    
     for(i=0;i<74;i++)
    {
        SDIO_CmdInitStructure.SDIO_Argument = 0x0;//发送CMD0进入IDLE STAGE模式命令.
    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_GO_IDLE_STATE; //cmd0
    SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_No;  //无响应
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;  //则CPSM在开始发送命令之前等待数据传输结束。 
    SDIO_SendCommand(&SDIO_CmdInitStructure);              //写命令进命令寄存器
        
        errorstatus=CmdError();
        if(errorstatus==SD_OK)break;
     }
     if(errorstatus)return errorstatus;//返回错误状态

    SDIO_CmdInitStructure.SDIO_Argument = SD_CHECK_PATTERN;    //发送CMD8,短响应,检查SD卡接口特性
  SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_SEND_IF_COND;    //cmd8
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;     //r7
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;             //关闭等待中断
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);
    
      errorstatus=CmdResp7Error();                        //等待R7响应
     if(errorstatus==SD_OK)                                 //R7响应正常
    {
        CardType=SDIO_STD_CAPACITY_SD_CARD_V2_0;        //SD 2.0卡
        SDType=SD_HIGH_CAPACITY;                           //高容量卡
    }
      SDIO_CmdInitStructure.SDIO_Argument = 0x00;//发送CMD55,短响应    
    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD;
    SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(&SDIO_CmdInitStructure);        //发送CMD55,短响应     
    
    errorstatus=CmdResp1Error(SD_CMD_APP_CMD);              //等待R1响应   
    if(errorstatus==SD_OK)//SD2.0/SD 1.1,否则为MMC卡
    {                                                                  
        //SD卡,发送ACMD41 SD_APP_OP_COND,参数为:0x80100000 
        while((!validvoltage)&&(count<SD_MAX_VOLT_TRIAL))
        {                                                  
          SDIO_CmdInitStructure.SDIO_Argument = 0x00;//发送CMD55,短响应
      SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD;      //CMD55
      SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
      SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
      SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
      SDIO_SendCommand(&SDIO_CmdInitStructure);            //发送CMD55,短响应     
            
            errorstatus=CmdResp1Error(SD_CMD_APP_CMD);          //等待R1响应   
             if(errorstatus!=SD_OK)return errorstatus;       //响应错误
            
      //acmd41,命令参数由支持的电压范围及HCS位组成,HCS位置一来区分卡是SDSc还是sdhc
      SDIO_CmdInitStructure.SDIO_Argument = SD_VOLTAGE_WINDOW_SD | SDType;    //发送ACMD41,短响应    
      SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_APP_OP_COND;
      SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;  //r3
      SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
      SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
      SDIO_SendCommand(&SDIO_CmdInitStructure);
            
            errorstatus=CmdResp3Error();                     //等待R3响应
            
             if(errorstatus!=SD_OK)return errorstatus;       //响应错误  
            response=SDIO->RESP1;;                               //得到响应
            validvoltage=(((response>>31)==1)?1:0);            //判断SD卡上电是否完成
            count++;
        }
        if(count>=SD_MAX_VOLT_TRIAL)
        {
            errorstatus=SD_INVALID_VOLTRANGE;
            return errorstatus;
        }     
        if(response&=SD_HIGH_CAPACITY)
        {
            CardType=SDIO_HIGH_CAPACITY_SD_CARD;
        }
     }else//MMC卡
    {
        //MMC卡,发送CMD1 SDIO_SEND_OP_COND,参数为:0x80FF8000 
        while((!validvoltage)&&(count<SD_MAX_VOLT_TRIAL))
        {                                                                     
            SDIO_CmdInitStructure.SDIO_Argument = SD_VOLTAGE_WINDOW_MMC;//发送CMD1,短响应       
      SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEND_OP_COND;
      SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;  //r3
      SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
      SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
      SDIO_SendCommand(&SDIO_CmdInitStructure);
            
            errorstatus=CmdResp3Error();                     //等待R3响应   
             if(errorstatus!=SD_OK)return errorstatus;       //响应错误  
            response=SDIO->RESP1;;                               //得到响应
            validvoltage=(((response>>31)==1)?1:0);
            count++;
        }
        if(count>=SD_MAX_VOLT_TRIAL)
        {
            errorstatus=SD_INVALID_VOLTRANGE;
            return errorstatus;
        }                     
        CardType=SDIO_MULTIMEDIA_CARD;      
      }  
      return(errorstatus);        
}
//SD卡 Power OFF
//返回值:错误代码;(0,无错误)
SD_Error SD_PowerOFF(void)
{
  SDIO_SetPowerState(SDIO_PowerState_OFF);//SDIO电源关闭,时钟停止    
    return SD_OK;          
}   
//初始化所有的卡,并让卡进入就绪状态
//返回值:错误代码
SD_Error SD_InitializeCards(void)
{
     SD_Error errorstatus=SD_OK;
    u16 rca = 0x01;
     if(SDIO_GetPowerState()==0)return SD_REQUEST_NOT_APPLICABLE;//检查电源状态,确保为上电状态
     if(SDIO_SECURE_DIGITAL_IO_CARD!=CardType)            //非SECURE_DIGITAL_IO_CARD
    {
        SDIO_CmdInitStructure.SDIO_Argument = 0x0;//发送CMD2,取得CID,长响应
    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_ALL_SEND_CID;
    SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(&SDIO_CmdInitStructure);//发送CMD2,取得CID,长响应    
        
        errorstatus=CmdResp2Error();                     //等待R2响应   
        if(errorstatus!=SD_OK)return errorstatus;       //响应错误            
         CID_Tab[0]=SDIO->RESP1;
        CID_Tab[1]=SDIO->RESP2;
        CID_Tab[2]=SDIO->RESP3;
        CID_Tab[3]=SDIO->RESP4;
    }
    if((SDIO_STD_CAPACITY_SD_CARD_V1_1==CardType)||(SDIO_STD_CAPACITY_SD_CARD_V2_0==CardType)||(SDIO_SECURE_DIGITAL_IO_COMBO_CARD==CardType)||(SDIO_HIGH_CAPACITY_SD_CARD==CardType))//判断卡类型
    {
        SDIO_CmdInitStructure.SDIO_Argument = 0x00;//发送CMD3,短响应 
    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_REL_ADDR;    //cmd3
    SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; //r6
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(&SDIO_CmdInitStructure);    //发送CMD3,短响应 
        
        errorstatus=CmdResp6Error(SD_CMD_SET_REL_ADDR,&rca);//等待R6响应 
        if(errorstatus!=SD_OK)return errorstatus;       //响应错误            
    }   
    if (SDIO_MULTIMEDIA_CARD==CardType)
    {
          SDIO_CmdInitStructure.SDIO_Argument = (u32)(rca<<16);//发送CMD3,短响应 
      SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_REL_ADDR;    //cmd3
      SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; //r6
      SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
      SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
      SDIO_SendCommand(&SDIO_CmdInitStructure);    //发送CMD3,短响应     
            
        errorstatus=CmdResp2Error();                     //等待R2响应   
        if(errorstatus!=SD_OK)return errorstatus;       //响应错误     
    }
    if (SDIO_SECURE_DIGITAL_IO_CARD!=CardType)            //非SECURE_DIGITAL_IO_CARD
    {
        RCA = rca;
    SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)(rca << 16);//发送CMD9+卡RCA,取得CSD,长响应 
    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEND_CSD;
    SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(&SDIO_CmdInitStructure);
        
        errorstatus=CmdResp2Error();                     //等待R2响应   
        if(errorstatus!=SD_OK)return errorstatus;       //响应错误            
          CSD_Tab[0]=SDIO->RESP1;
        CSD_Tab[1]=SDIO->RESP2;
        CSD_Tab[2]=SDIO->RESP3;                        
        CSD_Tab[3]=SDIO->RESP4;                        
    }
    return SD_OK;//卡初始化成功
} 
//得到卡信息
//cardinfo:卡信息存储区
//返回值:错误状态
SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo)
{
     SD_Error errorstatus=SD_OK;
    u8 tmp=0;       
    cardinfo->CardType=(u8)CardType;                 //卡类型
    cardinfo->RCA=(u16)RCA;                            //卡RCA值
    tmp=(u8)((CSD_Tab[0]&0xFF000000)>>24);
    cardinfo->SD_csd.CSDStruct=(tmp&0xC0)>>6;        //CSD结构
    cardinfo->SD_csd.SysSpecVersion=(tmp&0x3C)>>2;    //2.0协议还没定义这部分(为保留),应该是后续协议定义的
    cardinfo->SD_csd.Reserved1=tmp&0x03;            //2个保留位  
    tmp=(u8)((CSD_Tab[0]&0x00FF0000)>>16);            //第1个字节
    cardinfo->SD_csd.TAAC=tmp;                           //数据读时间1
    tmp=(u8)((CSD_Tab[0]&0x0000FF00)>>8);              //第2个字节
    cardinfo->SD_csd.NSAC=tmp;                          //数据读时间2
    tmp=(u8)(CSD_Tab[0]&0x000000FF);                //第3个字节
    cardinfo->SD_csd.MaxBusClkFrec=tmp;                  //传输速度       
    tmp=(u8)((CSD_Tab[1]&0xFF000000)>>24);            //第4个字节
    cardinfo->SD_csd.CardComdClasses=tmp<<4;        //卡指令类高四位
    tmp=(u8)((CSD_Tab[1]&0x00FF0000)>>16);             //第5个字节
    cardinfo->SD_csd.CardComdClasses|=(tmp&0xF0)>>4;//卡指令类低四位
    cardinfo->SD_csd.RdBlockLen=tmp&0x0F;            //最大读取数据长度
    tmp=(u8)((CSD_Tab[1]&0x0000FF00)>>8);            //第6个字节
    cardinfo->SD_csd.PartBlockRead=(tmp&0x80)>>7;    //允许分块读
    cardinfo->SD_csd.WrBlockMisalign=(tmp&0x40)>>6;    //写块错位
    cardinfo->SD_csd.RdBlockMisalign=(tmp&0x20)>>5;    //读块错位
    cardinfo->SD_csd.DSRImpl=(tmp&0x10)>>4;
    cardinfo->SD_csd.Reserved2=0;                     //保留
     if((CardType==SDIO_STD_CAPACITY_SD_CARD_V1_1)||(CardType==SDIO_STD_CAPACITY_SD_CARD_V2_0)||(SDIO_MULTIMEDIA_CARD==CardType))//标准1.1/2.0卡/MMC卡
    {
        cardinfo->SD_csd.DeviceSize=(tmp&0x03)<<10;    //C_SIZE(12位)
         tmp=(u8)(CSD_Tab[1]&0x000000FF);             //第7个字节    
        cardinfo->SD_csd.DeviceSize|=(tmp)<<2;
         tmp=(u8)((CSD_Tab[2]&0xFF000000)>>24);        //第8个字节    
        cardinfo->SD_csd.DeviceSize|=(tmp&0xC0)>>6;
         cardinfo->SD_csd.MaxRdCurrentVDDMin=(tmp&0x38)>>3;
        cardinfo->SD_csd.MaxRdCurrentVDDMax=(tmp&0x07);
         tmp=(u8)((CSD_Tab[2]&0x00FF0000)>>16);        //第9个字节    
        cardinfo->SD_csd.MaxWrCurrentVDDMin=(tmp&0xE0)>>5;
        cardinfo->SD_csd.MaxWrCurrentVDDMax=(tmp&0x1C)>>2;
        cardinfo->SD_csd.DeviceSizeMul=(tmp&0x03)<<1;//C_SIZE_MULT
         tmp=(u8)((CSD_Tab[2]&0x0000FF00)>>8);          //第10个字节    
        cardinfo->SD_csd.DeviceSizeMul|=(tmp&0x80)>>7;
         cardinfo->CardCapacity=(cardinfo->SD_csd.DeviceSize+1);//计算卡容量
        cardinfo->CardCapacity*=(1<<(cardinfo->SD_csd.DeviceSizeMul+2));
        cardinfo->CardBlockSize=1<<(cardinfo->SD_csd.RdBlockLen);//块大小
        cardinfo->CardCapacity*=cardinfo->CardBlockSize;
    }else if(CardType==SDIO_HIGH_CAPACITY_SD_CARD)    //高容量卡
    {
         tmp=(u8)(CSD_Tab[1]&0x000000FF);         //第7个字节    
        cardinfo->SD_csd.DeviceSize=(tmp&0x3F)<<16;//C_SIZE
         tmp=(u8)((CSD_Tab[2]&0xFF000000)>>24);     //第8个字节    
         cardinfo->SD_csd.DeviceSize|=(tmp<<8);
         tmp=(u8)((CSD_Tab[2]&0x00FF0000)>>16);    //第9个字节    
         cardinfo->SD_csd.DeviceSize|=(tmp);
         tmp=(u8)((CSD_Tab[2]&0x0000FF00)>>8);     //第10个字节    
         cardinfo->CardCapacity=(long long)(cardinfo->SD_csd.DeviceSize+1)*512*1024;//计算卡容量
        cardinfo->CardBlockSize=512;             //块大小固定为512字节
    }      
    cardinfo->SD_csd.EraseGrSize=(tmp&0x40)>>6;
    cardinfo->SD_csd.EraseGrMul=(tmp&0x3F)<<1;       
    tmp=(u8)(CSD_Tab[2]&0x000000FF);            //第11个字节    
    cardinfo->SD_csd.EraseGrMul|=(tmp&0x80)>>7;
    cardinfo->SD_csd.WrProtectGrSize=(tmp&0x7F);
     tmp=(u8)((CSD_Tab[3]&0xFF000000)>>24);        //第12个字节    
    cardinfo->SD_csd.WrProtectGrEnable=(tmp&0x80)>>7;
    cardinfo->SD_csd.ManDeflECC=(tmp&0x60)>>5;
    cardinfo->SD_csd.WrSpeedFact=(tmp&0x1C)>>2;
    cardinfo->SD_csd.MaxWrBlockLen=(tmp&0x03)<<2;     
    tmp=(u8)((CSD_Tab[3]&0x00FF0000)>>16);        //第13个字节
    cardinfo->SD_csd.MaxWrBlockLen|=(tmp&0xC0)>>6;
    cardinfo->SD_csd.WriteBlockPaPartial=(tmp&0x20)>>5;
    cardinfo->SD_csd.Reserved3=0;
    cardinfo->SD_csd.ContentProtectAppli=(tmp&0x01);  
    tmp=(u8)((CSD_Tab[3]&0x0000FF00)>>8);        //第14个字节
    cardinfo->SD_csd.FileFormatGrouop=(tmp&0x80)>>7;
    cardinfo->SD_csd.CopyFlag=(tmp&0x40)>>6;
    cardinfo->SD_csd.PermWrProtect=(tmp&0x20)>>5;
    cardinfo->SD_csd.TempWrProtect=(tmp&0x10)>>4;
    cardinfo->SD_csd.FileFormat=(tmp&0x0C)>>2;
    cardinfo->SD_csd.ECC=(tmp&0x03);  
    tmp=(u8)(CSD_Tab[3]&0x000000FF);            //第15个字节
    cardinfo->SD_csd.CSD_CRC=(tmp&0xFE)>>1;
    cardinfo->SD_csd.Reserved4=1;         
    tmp=(u8)((CID_Tab[0]&0xFF000000)>>24);        //第0个字节
    cardinfo->SD_cid.ManufacturerID=tmp;            
    tmp=(u8)((CID_Tab[0]&0x00FF0000)>>16);        //第1个字节
    cardinfo->SD_cid.OEM_AppliID=tmp<<8;      
    tmp=(u8)((CID_Tab[0]&0x000000FF00)>>8);        //第2个字节
    cardinfo->SD_cid.OEM_AppliID|=tmp;        
    tmp=(u8)(CID_Tab[0]&0x000000FF);            //第3个字节    
    cardinfo->SD_cid.ProdName1=tmp<<24;                  
    tmp=(u8)((CID_Tab[1]&0xFF000000)>>24);         //第4个字节
    cardinfo->SD_cid.ProdName1|=tmp<<16;      
    tmp=(u8)((CID_Tab[1]&0x00FF0000)>>16);           //第5个字节
    cardinfo->SD_cid.ProdName1|=tmp<<8;         
    tmp=(u8)((CID_Tab[1]&0x0000FF00)>>8);        //第6个字节
    cardinfo->SD_cid.ProdName1|=tmp;           
    tmp=(u8)(CID_Tab[1]&0x000000FF);              //第7个字节
    cardinfo->SD_cid.ProdName2=tmp;              
    tmp=(u8)((CID_Tab[2]&0xFF000000)>>24);         //第8个字节
    cardinfo->SD_cid.ProdRev=tmp;         
    tmp=(u8)((CID_Tab[2]&0x00FF0000)>>16);        //第9个字节
    cardinfo->SD_cid.ProdSN=tmp<<24;       
    tmp=(u8)((CID_Tab[2]&0x0000FF00)>>8);         //第10个字节
    cardinfo->SD_cid.ProdSN|=tmp<<16;       
    tmp=(u8)(CID_Tab[2]&0x000000FF);               //第11个字节
    cardinfo->SD_cid.ProdSN|=tmp<<8;           
    tmp=(u8)((CID_Tab[3]&0xFF000000)>>24);         //第12个字节
    cardinfo->SD_cid.ProdSN|=tmp;                 
    tmp=(u8)((CID_Tab[3]&0x00FF0000)>>16);         //第13个字节
    cardinfo->SD_cid.Reserved1|=(tmp&0xF0)>>4;
    cardinfo->SD_cid.ManufactDate=(tmp&0x0F)<<8;    
    tmp=(u8)((CID_Tab[3]&0x0000FF00)>>8);        //第14个字节
    cardinfo->SD_cid.ManufactDate|=tmp;               
    tmp=(u8)(CID_Tab[3]&0x000000FF);            //第15个字节
    cardinfo->SD_cid.CID_CRC=(tmp&0xFE)>>1;
    cardinfo->SD_cid.Reserved2=1;     
    return errorstatus;
}
//设置SDIO总线宽度(MMC卡不支持4bit模式)
//wmode:位宽模式.0,1位数据宽度;1,4位数据宽度;2,8位数据宽度
//返回值:SD卡错误状态
SD_Error SD_EnableWideBusOperation(u32 wmode)
{
      SD_Error errorstatus=SD_OK;
     if(SDIO_MULTIMEDIA_CARD==CardType)
        return SD_UNSUPPORTED_FEATURE;//MMC卡不支持
     else if((SDIO_STD_CAPACITY_SD_CARD_V1_1==CardType)||(SDIO_STD_CAPACITY_SD_CARD_V2_0==CardType)||(SDIO_HIGH_CAPACITY_SD_CARD==CardType))
    {
        if(wmode>=2)return SD_UNSUPPORTED_FEATURE;//不支持8位模式
         else   
        {
            errorstatus=SDEnWideBus(wmode);
             if(SD_OK==errorstatus)
            {
                SDIO->CLKCR&=~(3<<11);        //清除之前的位宽设置    
                SDIO->CLKCR|=(u16)wmode<<11;//1位/4位总线宽度 
                SDIO->CLKCR|=0<<14;            //不开启硬件流控制
            }
        }  
    }
    return errorstatus; 
}
//设置SD卡工作模式
//Mode:
//返回值:错误状态
SD_Error SD_SetDeviceMode(u32 Mode)
{
    SD_Error errorstatus = SD_OK;
     if((Mode==SD_DMA_MODE)||(Mode==SD_POLLING_MODE))DeviceMode=Mode;
    else errorstatus=SD_INVALID_PARAMETER;
    return errorstatus;        
}
//选卡
//发送CMD7,选择相对地址(rca)为addr的卡,取消其他卡.如果为0,则都不选择.
//addr:卡的RCA地址
SD_Error SD_SelectDeselect(u32 addr)
{

    SDIO_CmdInitStructure.SDIO_Argument =  addr;//发送CMD7,选择卡,短响应    
  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEL_DESEL_CARD;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);//发送CMD7,选择卡,短响应
    
     return CmdResp1Error(SD_CMD_SEL_DESEL_CARD);     
    
}

四、主函数展示
 

FIL fil;
FRESULT res1;
UINT bww;
extern int x_shock;
//char buf[100];
 int main(void)
 {	 
    u32 total,free;    	    
	char str[10];
//	int T; //X_shock,Y_shock,Z_shock 
	int X_Speed,Y_Speed,Z_Speed;
	delay_init();	    	 //延时函数初始化	
	SystemInit();	
 	LED_Init();	
    Modbus_RegMap();//modbus通讯  
	RS485_Init();//硬件层通讯使能
	uart_init(9600);	 	
	Timer4_enable(4999);	//250ms	通讯节拍控制器 	 //初始化与LED连接的硬件接口
//	KEY_Init();					//初始化按键 
 	my_mem_init(SRAMIN);		//初始化内部内存池  
//	while(SD_Init())//检测不到SD卡
//	{
//		delay_ms(500);
//		LED0=!LED0;//DS0闪烁
//	}
//	printf("检测不到SD卡\n");
	 Modbus_03_Solve();
 	exfuns_init();							//为fatfs相关变量申请内存				 
  	f_mount(fs[0],"0:",1); 					//挂载SD卡 
	while(exf_getfree("0",&total,&free))	//得到SD卡的总容量和剩余容量
	{	
		printf("total:%d\n",total);
		printf("free:%d\n",free);
		delay_ms(200);
		LED0=!LED0;//DS0闪烁
	}	
	while(1)
	{	Modbus_03_Solve();	
//		T=temp;
//		Y_shock=Y_Speed();
//		Z_shock=Z_Speed();
	   printf("速度:%d\n",x_shock);
		f_open (&fil,"0:/振动传感器数据.txt", FA_OPEN_ALWAYS|FA_WRITE);
		f_lseek (&fil,f_size (&fil));	
	   sprintf(str,"X_Speed:%d(mm/s)\t",X_Speed);//把数据存放在str里
		f_write (&fil, str ,sizeof(str), &bww);
		memset(str,0,sizeof(str)); //初始化数组的数据,方便下一个数据储存到数组里
		f_close(&fil);
		
	delay_ms(1000);		 			   
		LED1=!LED1;
	} 
}

欢迎大家一起学习和讨论

  • 5
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值