查看: 5190|回复: 0

[分享] i.MX RT1064函数库:USB模块和uSDHC模块

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3300

    主题

    6547

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32032
    最后登录
    2024-4-26
    发表于 2020-12-10 10:02:16 | 显示全部楼层 |阅读模式
    i.MX RT1064函数库:USB模块和uSDHC模块


    为方便参加恩智浦大学生智能车设计竞赛的同学们,成都逐飞科技设计制作了i.MX RT1064核心板,并配套开发了相应的函数库。
    本文为逐飞科技来稿,在此分享给大家,对不参加智能车竞赛的朋友也有很大的帮助作用。
    点此回顾往期内容:
    GPIO详解
    FAST GPIO模块详解与使用示例
    ADC模块和QTIMER模块
    PIT模块详解与使用示例
    UART模块详解与使用示例

    PWM和CACHE模块的使用

    I2C模块和SPI模块的使用
    NVIC模块和EFUSE模块



    各位朋友好,逐飞科技连载的“基于RT1064的智能车应用入门指导”开发分享又来投稿啦!今天分享USB & uSDHC两个模块的使用,主要讲解如何通过逐飞RT1064函数库来使用这两个模块以及相关注意事项。感谢恩智浦的支持,感谢梁平老师的支持以及帮忙检查修改文中错误,感谢关注“逐飞科技”。接下来进入我们今天分享的主题----“USB模块使用示例”&“uSDHC模块使用示例”:


    USB模块使用示例

    1. USB功能


    USB(Universal Serial Bus)通用串行总线是迄今为止使用最广泛的一种总线。具有接线数量少、速度快等特点。USB版本有1.0、1.1、2.0、3.0、3.1、3.2、4.0,USB 1.0版本只支持低速1.5Mbps,USB1.1支持全速12Mbps,USB2.0支持高速480Mbps,USB3.0支持超高速5Gbps,USB3.1支持超高速+10Gbps,USB3.2支持超高速++20Gbps,USB4.0速度高达40Gbps。这里需要注意的是USB2.0版本的设备不一定能支持480Mbps,有可能USB2.0的设备仅仅能支持全速,只是支持USB2.0的协议而已。


    在RT1064片内的USB是USB2.0版本的,并且可以支持高速480Mbps。


    2. USB库函数


    以下函数均位于zf_usb_cdc.c和zf_usb_cdc.h:
    11.png
    usb_cdc_send_char函数参数
    12.png
    usb_cdc_send_str函数参数
    13.png
    usb_cdc_send_buff函数参数
    14.png
    USB使用示例


    USB发送数据
    1. #include "headfile.h"  

    2. //使用本例程请使用type C数据线连接核心板与电脑  
    3. //使用usb虚拟串口请务必注意操作顺序  
    4. //1下载程序并运行  
    5. //2打开串口助手选择对应的串口并打开即可收到数据  
    6. //3如果程序复位之后,则串口助手需要关闭然后在打开  
    7. int main(void)  
    8. {  
    9.     DisableGlobalIRQ();  
    10.     board_init();//务必保留,本函数用于初始化MPU时钟 调试串口
    11.       
    12.     usb_cdc_init();//初始化USB 虚拟串口

    13.     //总中断最后开启  
    14.     EnableGlobalIRQ(0);  
    15.     while (1)  
    16.     {
    17.         usb_cdc_send_str("Seekfree USB CDC Test\n");  
    18.         systick_delay_ms(500);  
    19.         //此处编写需要循环执行的代码
    20.     }  
    21. }
    复制代码
    使用注意事项:如果电脑中没有usb虚拟串口的驱动,则需要自己安装驱动,驱动文件可以通过查看库例程16-USB CDC Demo中获得。如果电脑中能直接识别出COM端口则可以不用安装驱动。

    uSDHC模块使用示例


    1. uSDHC功能


    uSDHC(Ultra Secured Digital Host Controller)是超安全数字主机控制器。


    RT1064的uSDHC功能如下:


    1、符合SD主机控制器的标准规范2.0/3.0版本。
    2、兼容MMC卡规范4.2/ 4.3/ 4.4/ 4.41/ 4.5版本。
    3、兼容SD卡规范3.0版本,并支持SDXC卡。
    4、兼容SDIO卡规范2.0/3.0版本。
    5、卡总线时钟频率高达208 MHz。
    6、SD和SDIO模式支持1bit/4bit,MMC模式支持1bit/4bit/8bit。
    7、支持连接SD(最大容量2G)、SDHC(最大容量32G)、SDXC(最大容量2048GB)卡。


    2. uSDHC库函数


    以下函数位于zf_sdcard.c和zf_sdcard.h:
    15.png
    sdcard_wait_card_insert函数返回值
    16.png
    uSDHC使用示例

    使用fatfs文件系统创建文件
    1. #include "headfile.h"  

    2. //----------------特别注意----------------  
    3. //----------------特别注意----------------  
    4. //----------------特别注意----------------  
    5.   
    6. //本例程运行后会降卡全部格式化,请小心使用  
    7.   
    8. //----------------特别注意----------------  
    9. //----------------特别注意----------------  
    10. //----------------特别注意----------------  
    11. #define BUFFER_SIZE (512U)  
    12. static FATFS g_fileSystem; //文件系统结构体变量
    13. static FIL g_fileObject;   //文件结构体变量
    14. //写入缓冲区
    15. AT_DTCM_SECTION_ALIGN(uint8_t g_bufferWrite[SDK_SIZEALIGN(BUFFER_SIZE, SDMMC_DATA_BUFFER_ALIGN_CACHE)],MAX(SDMMC_DATA_BUFFER_ALIGN_CACHE, SDMMCHOST_DMA_BUFFER_ADDR_ALIGN));  
    16.   
    17. //读取缓冲区
    18. AT_DTCM_SECTION_ALIGN(uint8_t g_bufferRead[SDK_SIZEALIGN(BUFFER_SIZE, SDMMC_DATA_BUFFER_ALIGN_CACHE)], MAX(SDMMC_DATA_BUFFER_ALIGN_CACHE, SDMMCHOST_DMA_BUFFER_ADDR_ALIGN));  
    19.   
    20. //SD卡需要使用的引脚有 B23 C30 D4 D12 D13 D14 D15 D16 D17  
    21. //如果核心板插在主板上的请确认这些端口是没有连接其他外设(确认拨码开关处于OFF 且没有插  舵机、运放模块、2寸IPS并口屏幕、无线转串口模块)  
    22. //否则有可能导致例程无法使用  
    23.   
    24. //在使用前请将核心板的J1 J3跳线焊接起来。
    25. //----------------特别注意----------------  
    26. //----------------特别注意----------------  
    27. //----------------特别注意----------------  
    28.   
    29. //本例程运行后会将卡全部格式化,请小心使用  
    30.   
    31. //----------------特别注意----------------  
    32. //----------------特别注意----------------  
    33. //----------------特别注意----------------  
    34. int main(void)  
    35. {  
    36.     FRESULT error;  
    37.     DIR directory; //目录结构体变量  
    38.     FILINFO fileInformation;  
    39.     UINT bytesWritten;  
    40.     UINT bytesRead;  
    41.     const TCHAR driverNumberBuffer[3U] = {SDDISK + '0', ':', '/'};  
    42.     volatile bool failedFlag = false;  
    43.     char ch = '0';  
    44.     BYTE work[FF_MAX_SS];  
    45.       
    46.     DisableGlobalIRQ();  
    47.     board_init();//务必保留,本函数用于初始化MPU时钟 调试串口  
    48.   
    49.       
    50.     sdcard_clk_init();//初始化SDHC时钟

    51.     //总中断最后开启
    52.     EnableGlobalIRQ(0);  
    53.   
    54.       
    55.     PRINTF("\r\nFATFS 文件系统示例程序\r\n");  
    56.   
    57.     PRINTF("\r\n请插入SD卡\r\n");  

    58.     //等待SD卡插入  
    59.     if (sdcard_wait_card_insert() != kStatus_Success)  
    60.     {  
    61.         return -1;  
    62.     }  
    63.   
    64.     if (f_mount(&g_fileSystem, driverNumberBuffer, 0U))  
    65.     {  
    66.         PRINTF("挂载失败\r\n");  
    67.         return -1;  
    68.     }  
    69.   
    70. #if (FF_FS_RPATH >= 2U)  
    71.     error = f_chdrive((char const *)&driverNumberBuffer[0U]);  
    72.     if (error)  
    73.     {  
    74.         PRINTF("改变驱动器失败\r\n");  
    75.         return -1;  
    76.     }  
    77. #endif  
    78.   
    79. #if FF_USE_MKFS  
    80.     PRINTF("\r\n创建文件系统中。。。这可能需要一个比较长的时间\r\n");  
    81.     //当SD卡文件系统创建完毕之后,就不需要在每次都创建了
    82.     //因为每次创建都是会把SD卡格式化一遍的,每次都格式化容易导致卡报废   
    83.     if (f_mkfs(driverNumberBuffer, FM_ANY, 0U, work, sizeof work))  
    84.     {  
    85.         PRINTF("创建文件系统失败\r\n");  
    86.         return -1;  
    87.     }  
    88.     SD_PowerOffCard(g_sd.host.base, g_sd.usrParam.pwr); //创建文件系统后关闭SD卡电源  
    89.     SD_PowerOnCard(g_sd.host.base, g_sd.usrParam.pwr);  //打开sd卡电源  
    90. #endif /* FF_USE_MKFS */  
    91.   
    92.     PRINTF("\r\n创建目录中\r\n");  
    93.     error = f_mkdir(_T("/dir_1"));  
    94.     if (error)  
    95.     {  
    96.         if (error == FR_EXIST)  
    97.         {  
    98.             PRINTF("目录已存在\r\n");  
    99.         }  
    100.         else  
    101.         {  
    102.             PRINTF("目录创建失败\r\n");  
    103.             return -1;  
    104.         }  
    105.     }  
    106.   
    107.     PRINTF("\r\n创建一个文件在当前目录下\r\n");  
    108.     error = f_open(&g_fileObject, _T("/dir_1/f_1.dat"), (FA_WRITE | FA_READ | FA_CREATE_ALWAYS));  
    109.     if (error)  
    110.     {  
    111.         if (error == FR_EXIST)  
    112.         {  
    113.             PRINTF("文件已存在\r\n");  
    114.         }  
    115.         else  
    116.         {  
    117.             PRINTF("创建文件失败\r\n");  
    118.             return -1;  
    119.         }  
    120.     }  
    121.   
    122.     PRINTF("\r\n在当前目录中,再创建一个目录\r\n");  
    123.     error = f_mkdir(_T("/dir_1/dir_2"));  
    124.     if (error)  
    125.     {  
    126.         if (error == FR_EXIST)  
    127.         {  
    128.             PRINTF("目录以存在\r\n");  
    129.         }  
    130.         else  
    131.         {  
    132.             PRINTF("目录创建失败\r\n");  
    133.             return -1;  
    134.         }  
    135.     }  
    136.   
    137.     PRINTF("\r\n列出该目录中的文件\r\n");  
    138.     if (f_opendir(&directory, "/dir_1"))  
    139.     {  
    140.         PRINTF("目录打开失败\r\n");  
    141.         return -1;  
    142.     }  
    143.   
    144.     for (;;)  
    145.     {  
    146.         error = f_readdir(&directory, &fileInformation);  
    147.   
    148.         /* To the end. */  
    149.         if ((error != FR_OK) || (fileInformation.fname[0U] == 0U))  
    150.         {  
    151.             break;  
    152.         }  
    153.         if (fileInformation.fname[0] == '.')  
    154.         {  
    155.             continue;  
    156.         }  
    157.         if (fileInformation.fattrib & AM_DIR)  
    158.         {  
    159.             PRINTF("文件夹 : %s.\r\n", fileInformation.fname);  
    160.         }  
    161.         else  
    162.         {  
    163.             PRINTF("普通文件 : %s.\r\n", fileInformation.fname);  
    164.         }  
    165.     }  
    166.   
    167.     memset(g_bufferWrite, 'a', sizeof(g_bufferWrite));  
    168.     g_bufferWrite[BUFFER_SIZE - 2U] = '\r';  
    169.     g_bufferWrite[BUFFER_SIZE - 1U] = '\n';  
    170.   
    171.     PRINTF("\r\n写入/读取文件,直到遇到错误\r\n");  
    172.     while (true)  
    173.     {  
    174.         if (failedFlag || (ch == 'q'))  
    175.         {  
    176.             break;  
    177.         }  
    178.   
    179.         PRINTF("\r\n写入数据到上面创建的文件\r\n");  
    180.         error = f_write(&g_fileObject, g_bufferWrite, sizeof(g_bufferWrite), &bytesWritten);  
    181.         if ((error) || (bytesWritten != sizeof(g_bufferWrite)))  
    182.         {  
    183.             PRINTF("写入文件失败 \r\n");  
    184.             failedFlag = true;  
    185.             continue;  
    186.         }  
    187.   
    188.         /* Move the file pointer */  
    189.         if (f_lseek(&g_fileObject, 0U))  
    190.         {  
    191.             PRINTF("设置文件指针位置失败\r\n");  
    192.             failedFlag = true;  
    193.             continue;  
    194.         }  
    195.   
    196.         PRINTF("读取上面创建的文件\r\n");  
    197.         memset(g_bufferRead, 0U, sizeof(g_bufferRead));  
    198.         error = f_read(&g_fileObject, g_bufferRead, sizeof(g_bufferRead), &bytesRead);  
    199.         if ((error) || (bytesRead != sizeof(g_bufferRead)))  
    200.         {  
    201.             PRINTF("读取文件失败\r\n");  
    202.             failedFlag = true;  
    203.             continue;  
    204.         }  
    205.   
    206.         PRINTF("开始比较写入与读取数据是否一致\r\n");  
    207.         if (memcmp(g_bufferWrite, g_bufferRead, sizeof(g_bufferWrite)))  
    208.         {  
    209.             PRINTF("写入与读取数据不一致\r\n");  
    210.             failedFlag = true;  
    211.             continue;  
    212.         }  
    213.         PRINTF("写入与读取数据一致\r\n");  
    214.   
    215.         PRINTF("\r\n输入q退出程序 输入其他重复执行写入与读取\r\n");  
    216.         ch = GETCHAR();  
    217.         PUTCHAR(ch);  
    218.     }  
    219.     PRINTF("\r\n示例程序不会再进行读取操作\r\n");  
    220.   
    221.     if (f_close(&g_fileObject))  
    222.     {  
    223.         PRINTF("\r\n关闭文件失败\r\n");  
    224.         return -1;  
    225.     }  
    226.   
    227.     while (true)  
    228.     {  
    229.     }  
    230. }
    复制代码
    编程要点:操作SD卡,主要通过fatfs文件系统来实现。fatfs属于开源的软件,具体的操作大家可以从网络上了解到很多相关的知识。
    使用注意事项:在使用前请将核心板的J1 J3跳线焊接起来。

    签到签到
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-27 07:02 , Processed in 0.104322 second(s), 19 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表