请选择 进入手机版 | 继续访问电脑版

 找回密码
 立即注册
查看: 2457|回复: 17

TF卡读写和USB-CDC/虚拟串口数据传送例程-基于STC32

[复制链接]
  • TA的每日心情
    无聊
    2023-11-26 13:41
  • 签到天数: 1 天

    [LV.1]初来乍到

    14

    主题

    85

    回帖

    605

    积分

    高级会员

    积分
    605
    发表于 2023-3-15 16:35:48 | 显示全部楼层 |阅读模式
    这是一个使用STC32G12K128TF卡读写程序,
          TF卡优点是体积小,成本低,容量大,存取速度快。
       本例程任务是把一幅图像从上位机下载到MCU并写入TF卡。再从TF卡读出。显示在MCU的彩屏上。借此验证TF卡读写程序的工作和USB-CDC下载的操作细节。
       程序中使用了硬件SPITF卡通讯,LCM_DMA驱动彩屏显示。SPIP3口,LCMP2口。
    TF卡在使用上有个特殊的地方,就是初始化时要求mcu运行频率很低,而正常读写时要求高的运行频率,本例程使用了STC32G12K128灵活的频率变换特性和异步运行特性,很好的满足了TF卡初始化与正常读写时对频率的不同要求。既保证了系统的可靠性,又提高了速度。
       为方便有兴趣的朋友移植,本例程采用了模块化编程。主要模块如下:
    SD.C        //ft卡读写函数
    usb_initia.c   //usb-cdc打开命令
    tft_320_drv.c  //tft彩屏驱动函数,这个函数与使用的屏有关,不同的屏请换用相应的驱动
    main.c       //主函数
    stc_usb_cdc_32g.lib  //stc官方的cdc驱动库
       下面是主函数,
    #include "SD.h"
    #include "tft_320_drv.h"
    #include "usb_initial.h"
    #include "mcu_initial.h"
    #include "stc32g.h"
    #include "stc32_stc8_usb.h"
    #include "string.h"
    char *USER_DEVICEDESC=NULL;
    char *USER_PRODUCTDESC=NULL;
    char *USER_STCISPCMD="@STCISP*";
    u8 extern xdata  MCU_write_SD_data[];
    u8 extern xdata  MCU_read_SD_data[];
    extern BYTE xdata UsbInBuffer[64];
    extern BYTE xdata UsbOutBuffer[64];
    void main()
    {
            unsigned char xdata *qq;//写卡缓存的指针,用于usb下载数据向写卡缓存转移数据
            unsigned int i,cnt,cnt0,j,k,cc;
            mcu_initial();
       SD_init();    //SD卡初始化(SD卡读写速度在SD_init函数中设置)
             Delay10ms();
      HSCLKDIV=2;//担心速度太快写卡出错。降一下速,主频35M,读写tf卡速度35/4=8.75M
    SPCTL|=3;
                    delay(22);
            lcd_initial();
            display_black();//清屏对调试程序有利
            digit_display(0,0,1234);//在屏上显示个数据,当欢迎词用
                    delay(22);
      usb_initial();//usb-cdc
      j=0;i=0;
            digit_display(0,64,1234);//在屏上显示个数据,表示通过usb初始化
            strcpy(UsbInBuffer,"data_transffer_over");//准备了一个在上位机显示的结束用语
            cc=1;//循环状态
            cnt0=299;//(320x240x2/512-1=299)准备接收的扇区数
            cnt=0;//正在接收的扇区
            k=0;//辅助计数
      qq=MCU_write_SD_data;//写卡缓存指针初始化
    while(cc)
    {
            if(bUsbOutReady)//查询是否有信息过来。没有的话就继续查询,有信息就进入信息处理程序
            {
        memcpy(qq, UsbOutBuffer, 64);  //将接收数据(UsbOutBuffer)复制到写卡缓冲区(MCU_write_SD_data),应该用OutNumber替代64
        if(OutNumber<64)cc=1;//OutNumber小于64说明发送完了。后面没有数据可发了
            qq=qq+64;//移动写卡缓存指针,准备存放下一组接收到的数据
            k++;
                    if(k>7)//写卡处理,注意这样最后八组数据可能没有写上tf
                    {
              MCU_write_SD_512Byte(4730+cnt,512);//MCUSD卡写入数据,一次最多512字节        k=0;
                    qq=MCU_write_SD_data;//写卡缓存指针复位
      cnt++;
                    }
                    usb_OUT_done();//准备再次接收

            }
        if(cnt>cnt0)cc=0;//写入扇区数达到预定的值,退出接收状态
    }
       USB_SendData(UsbInBuffer,19);//向上位机发送数据,表示接收数据完成
       lcd_address(0,0,320,240);//设定写屏窗口
       for(i=0;i<cnt0;i++)
       {
            MCU_read_SD_512Byte(4730+i,512);//MCUSD卡读取512字节数据,                Delay10ms();
            lcm_dma_only(512,MCU_read_SD_data);//把读出的数据送屏显示
            while(!(DMA_LCM_STA&0x01));//因为读卡与刷屏用了同一个缓冲区,所以要等待dma完成,
       }
    while(1);
            }
    可以看到主函数里调用的函数
    1、SD_initial()
        这个函数的构架是在网上下载的,根据我自己的理解做了改动。另外,它使用了stc32g12k128的硬件SPI功能,选择的P3口与tf卡通讯。并使用了两个语句使运行频率下降
      HSCLKDIV=9;//这是重点
            SPI_init(2);//硬件SPI初始化
       系统主频采用的是35M,这两个语句使得SPI的运行频率为:
    35000000/9/16=243055HZ;低于400K,满足tf卡初始化的要求
    2、Lcd_initial()
        这是对应显示屏的初始化程序,不同的显示屏要换用自己相应的初始化函数,我使用了一款320X240并口彩屏,2.4吋。
    对屏初始化前,运行了两个语句,用来提高spi运行速度。
      HSCLKDIV=2;//担心速度太快写卡出错。降一下速,主频35M,读写tf卡速度35/4=8.75M
            SPCTL|=3;
    3、Digit_display()
    这是屏驱动里的函数,用于在屏上显示数字,方便调试
    4、Usb_initial()
        这是开启cdc通讯的函数,执行它,就能与上位机进行cdc通讯了。当然通讯是相互的,上位机也要打开相应的串口。这里我直接使用了stc-isp工具上的串口功能。(据说其它串口工具也一样用,我没试)
    5、Strcpy()
    这是C语言自带的拷贝函数,不多说
    6、Memcpy()
    这个也是C语言自带的拷贝函数。
    7、MCU_write_SD_512Byte(4730+cnt,512)
        把写卡缓冲区的数据写入tf卡指定扇区。第一个参数是扇区的位置,第二个参数是数据的字节数,最多512,没必要少,因为tf卡是按扇区写入的。扇区位置一般不要从零开始,那里通常是tf卡管理信息存放的位置。另外做实验时也不要一直在一个位置反复写入,每次实验都换个起始位置比较好。要考虑卡的写入寿命。
    8、USB_SendData(UsbInBuffer,19)
        把发送缓冲区的数据发送给上位机(也就是电脑)第一个参数表示数据的存放位置,第二个参数是发送的字节数。前面我把19字节的信息依次存入数组,现在可以用这个指令发送给上位机了。
    strcpy(UsbInBuffer,"data_transffer_over");//这是存入信息的语句,字符串的长度是19
    9、MCU_read_SD512Byte(4730+i,512)
       把指定扇区的数据读入读卡缓冲区,第一个参数是tf卡上扇区的位置,第二个参数是读出的字节数,读出的数据存放在读卡缓冲区MCU_read_SD_data[]
    10、Lcm_dma_only(512,MCU_read_SD_data)
        把缓冲区的数据送到彩屏上显示,第一个参数是字节数,第二个是数据存放位置。本来dma要有自己的专用缓冲区,为了编程简单,我直接用读卡缓冲区做dma缓冲区了。如果想提高速度,可以采用双缓冲区结构,一个读卡,一个显示,然后再换过来,这样把读卡和显示的速度都发挥出来。
        在主程序中,接收上位机的数据采用了循环查询的方式
    while(cc)
    {      
    if(bUsbOutReady)//查询是否有信息。没有就继续查询,有信息就进入信息处理程序
    {...信息处理
                    usb_OUT_done();//准备再次接收
    }
    }
        它的工作模式是,
        先查询标志位,看看上位机是否发送信息完成,
        如果没有。就循环继续查询
        如果上位机发送信息完成,则进入信息处理程序
        处理完信息,做接收下次信息的准备
        运行这段程序前设置了接收完成的条件cnt0,在程序中进行判断。
        为使用这个例程,我找了一个图像,使用软件把它裁剪成320X240尺寸,再转换成二进制文件(.bin).备用。
    程序执行时,打开stc-isp软件,切换到USB-CDC/串口助手。右键“发送文件”,调出设置界面,在设置界面上设置发送包5121024也能用),延时间隔用2毫秒(用1毫秒时数据出现错误)。确定后左键“发送文件”,找到准备好的二进制数据文件,确认后串口自动打开,并开始向mcu发送数据,在接收缓冲窗口上能看到快速发送的数据。每个包512字节。发送完成后,mcu向上位机发送信息data_transffer_over也在接收缓冲区显示出来。然后mcu的彩屏很快显示出从tf卡读出的数据图像。感觉速度比从code数组读出的速度要快不少。
        图片裁剪使用的工具是:
    提取图片数据V5.exe
        转化图片数据使用的工具是:
    Img2lcd.exe.
        验证时使用的tf卡是256M的行车记录仪储存卡。
    完整程序见附件。
    程序运行完后使用winhex软件查看了tf卡的信息。
    过程中使用的bin文件我压缩了一下,不知解压后能不能正常使用

    整机

    整机

    彩屏

    彩屏

    图像

    图像

    发送文件设置

    发送文件设置
    内存图.png

    tf_usb.zip

    204.59 KB, 下载次数: 123

    明湖bin.zip

    79.25 KB, 下载次数: 94

    回复 送花

    使用道具 举报

  • TA的每日心情
    奋斗
    2023-12-5 13:56
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    12

    主题

    233

    回帖

    1452

    积分

    超级版主

    积分
    1452
    发表于 2023-3-15 17:04:20 | 显示全部楼层
    感谢楼主的开源分享,非常适合初学者。:)
    电话:0513-55012946 QQ:2195591714  微信:  19952583740
  • TA的每日心情
    开心
    12 小时前
  • 签到天数: 122 天

    [LV.7]常住居民III

    17

    主题

    326

    回帖

    1063

    积分

    荣誉版主

    积分
    1063
    发表于 2023-3-20 17:59:43 | 显示全部楼层
    能否再成串口U盘
  • TA的每日心情
    无聊
    2023-11-26 13:41
  • 签到天数: 1 天

    [LV.1]初来乍到

    14

    主题

    85

    回帖

    605

    积分

    高级会员

    积分
    605
     楼主| 发表于 2023-3-20 18:39:51 | 显示全部楼层
    U盘的优点是容量大,超过MCU应用的需要,而且速度并不快,我本打算做个U盘例程的,但权衡半天感觉没什么价值。像TF卡512M时就能就会一般需要的,

    该用户从未签到

    3

    主题

    5

    回帖

    53

    积分

    注册会员

    积分
    53
    发表于 2023-5-29 19:58:51 | 显示全部楼层
    卡在命令1跳不出去。。。
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    2023-11-26 13:41
  • 签到天数: 1 天

    [LV.1]初来乍到

    14

    主题

    85

    回帖

    605

    积分

    高级会员

    积分
    605
     楼主| 发表于 2023-5-30 09:15:46 | 显示全部楼层
    carlkacl 发表于 2023-5-29 19:58
    卡在命令1跳不出去。。。

    怎么知道是卡在命令1?
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    3

    主题

    5

    回帖

    53

    积分

    注册会员

    积分
    53
    发表于 2023-5-30 09:28:50 | 显示全部楼层
    我在命令1的while循环里加了个计数器,计数到200退出并且返回自定义的整数(2),然后程序向串口发出这个整数。。
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    2023-11-26 13:41
  • 签到天数: 1 天

    [LV.1]初来乍到

    14

    主题

    85

    回帖

    605

    积分

    高级会员

    积分
    605
     楼主| 发表于 2023-5-30 14:14:12 | 显示全部楼层
    我想问三件事。一是用了什么mcu芯片,二是TF卡容量是多大的,三你说的程序是不是这个帖子里附件里的程序,或者修改时改了多少内容?
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    3

    主题

    5

    回帖

    53

    积分

    注册会员

    积分
    53
    发表于 2023-5-30 14:32:25 | 显示全部楼层
    丽江春水 发表于 2023-5-30 14:14
    我想问三件事。一是用了什么mcu芯片,二是TF卡容量是多大的,三你说的程序是不是这个帖子里附件里的程序, ...

    芯片就是stc32g128k,容量是16g的,改的话可能速度改了,但是也接近(400kHz以下),我再排查排查
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    无聊
    2023-11-26 13:41
  • 签到天数: 1 天

    [LV.1]初来乍到

    14

    主题

    85

    回帖

    605

    积分

    高级会员

    积分
    605
     楼主| 发表于 2023-5-30 14:38:11 | 显示全部楼层
    这个程序不能用在16g的卡上,只在512和256M的卡上测试通过,4G卡就不行了。原因是程序中缺少了卡的属性鉴别及相应的处理部分。
    回复 支持 反对 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-3-28 18:50 , Processed in 0.074728 second(s), 68 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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