最近在研究Linux过程中有点插曲,先不表了,于是就想着把SD卡研究一下,这个以前也没有搞过,找了stm32f767的例程,在此基础上更改了一下,可以在stm32f769上使用,就开始了SD卡的研究,个人钟爱寄存器配置的,没办法,就是对ST提供的库不感冒,有相同癖好的进来探讨,闲言少叙,进入正题。 看了f767板子的寄存器版本的指导书,正好也是和STM32F769DISCOVERY电路一样,都是非SPI接口的,可以参考其例程了,于是边参考st官方的例程STM32F769I-Discovery\Applications\Display\LCD_PicturesFromSDCard,边参考f767的例程,比较着修改, 先看看电路图0 E5 P4 t" e& e% N7 P' n' w( v 对应的IO分别是PG9,PG10,PB3,PB4,PD6,PD7,PI156 `# V1 Y2 L u' q: C' i 于是开始配置IO *(uint32_t *)0x40023830 |= 0x14a; //使能PORTB\D\G\I时钟 *(uint32_t *)0x40023830 |= 0x400000; //使能dma2时钟 *(uint32_t *)0x40023844 |= 0x80;//SDMMC2时钟使能3 X$ l4 ]- E% s8 Y& f+ } *(uint32_t *)0x40023824 |= 0x80;//SDMMC2复位& c1 I0 @/ p8 e) G' L c" A GPIO_Set(GPIOB,PIN3|PIN4,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PB3,PB4设置 GPIO_AF_Set(GPIOB,3,10); //PB3,AF10 GPIO_AF_Set(GPIOB,4,10); //PB4,AF10 GPIO_Set(GPIOD,PIN6|PIN7,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PB3,PB4设置 GPIO_AF_Set(GPIOD,6,11); //PB6,AF11) ^6 E* ^+ ]& }$ J( R% @ GPIO_AF_Set(GPIOD,7,11); //PB7,AF11$ M( |, q1 K8 @9 B9 B# Z; l/ w9 { GPIO_Set(GPIOG,PIN9|PIN10,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PB3,PB4设置 GPIO_AF_Set(GPIOG,9,11); //PB9,AF11 GPIO_AF_Set(GPIOG,10,11); //PB10,AF11" C1 t! n6 X) M( d GPIO_Set(GPIOI,PIN15,GPIO_MODE_IN,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PI15设置 5 Q) R. u1 m1 E. U+ }( ?- V; u5 ^ *(uint32_t *)0x40023824 &= ~(0x80);//SDMMC2复位 这里是在f767的模板基础上改的,所以没有完全改成纯寄存器版本的,这个后续研究,然后再发帖。! L* R/ ]1 X) N s+ T IO配置完成后,开始清理SDMMC的所有寄存器 //SDMMC外设寄存器设置为默认值 SDMMC2->POWER=0x00000000;5 Q" K; C9 a$ _5 L4 z SDMMC2->CLKCR=0x00000000;& E( S, o. { a0 K SDMMC2->ARG=0x00000000; SDMMC2->CMD=0x00000000; SDMMC2->DTIMER=0x00000000; SDMMC2->DLEN=0x00000000; SDMMC2->DCTRL=0x00000000; SDMMC2->ICR=0x00C007FF; SDMMC2->MASK=0x00000000; 增加SD卡的中断配置, R9 k( ]& H" j* F' S MY_NVIC_Init(0,0,SDMMC2_IRQn,2); //SDMMC中断配置7 @, z/ w1 o+ U 完成后,开始进行上电操作, SD_PowerON();% b6 _; z6 F( h" c) W' P SD_InitializeCards(); //初始化SD卡 SD_GetCardInfo(&SDCardInfo); //获取卡信息- T6 f3 w+ r0 D' c9 h# {+ p) u SD_SelectDeselect((u32)(SDCardInfo.RCA<<16));//选中SD卡8 n9 \# b4 F; p SD_EnableWideBusOperation(1); //4位宽度,如果是MMC卡,则不能用4位模式 % t8 C b" s5 `/ L# [9 k( Z$ N # T$ k- s# u% H' D 以上实现了检测SD卡的类型,具体设置SD卡的时钟频率。 if(SDCardInfo.CardType==STD_CAPACITY_SD_CARD_V1_1||SDCardInfo.CardType==STD_CAPACITY_SD_CARD_V2_0)3 L) B8 F: X" ^3 e! _ {% A4 X1 l1 B. d5 _! }. C clkdiv=SDMMC_TRANSFER_CLK_DIV+2; //V1.1/V2.0卡,设置最高48/4=12Mhz }else clkdiv=SDMMC_TRANSFER_CLK_DIV; //SDHC等其他卡,设置最高48/2=24Mhz SDMMC_Clock_Set(clkdiv); //设置时钟频率,SDMMC时钟计算公式:SDMMC_CK时钟=SDMMCCLK/[clkdiv+2];其中,SDMMCCLK固定为48Mhz 3 x6 H) I' u! I L) R$ U 暂且设置成查询模式,后续再改成中断模式 SD_SetDeviceMode(SD_POLLING_MODE);//设置为查询模式 : a7 G! c; v7 f/ M" G" R 初始化完成后,在main函数下添加以下代码实现SD卡的初始化操作 while(sdcard_init())//检测不到SD卡% v2 d9 e0 [. N& R { delay_ms(500);' a7 X8 F2 @8 O, z1 o& [8 x LED0(led0sta^=1);//DS0闪烁 } # A+ I' F# K7 \) l7 M 在while(1)添加代码,检查SD卡初始化是否完成,代码是否继续运行 {7 }% y- A! D1 w& C$ _% _ delay_ms(500);& t! F; D1 e" Y- ` printf("\r\n sd is ok!:\r\n");7 f( N( v* X- o) z4 K }4 U" G! K! y2 V3 ] 果然串口一直在打印输出 , Z$ \ c! B4 K4 R 说明SD卡初始化完成了 详细的代码说明,后面会陆续有新帖,喜欢寄存器配置的网友,自行关注! $ d0 N1 g: e5 S8 b0 u5 i7 F ) B. ]( Y( m6 w' q 发帖与2018年3月9日! l; X; S2 A( L+ T' b 3 ?) Y6 _ y6 ?; n/ c6 o 7 U6 Z! Y: X9 n$ n: T5 m 继续阅读:stm32f769 寄存器配置SD卡--打印SD卡信息1 x& @$ [5 v' F3 @$ ~9 ? |
https://www.stmcu.org.cn/module/forum/thread-615031-1-1.html
https://www.stmcu.org.cn/module/forum/thread-615032-1-1.html