找回密码
 立即注册
查看: 842|回复: 5

IIC-DMA读写at24c1024例程分享与解析-基于stc32g12k128的应用

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

    [LV.1]初来乍到

    14

    主题

    85

    回帖

    609

    积分

    高级会员

    积分
    609
    发表于 2023-2-26 17:29:37 | 显示全部楼层 |阅读模式
      分享该例程是因为虽然网上已经有很多关于at24c芯片的读写程序,可是我在不停查资料的情况下还是用了十天时间才把程序调通。查到的每个资料都对我有帮助,但仍不够用。考虑到其它新人或者会遇到同样的情况,决定把程序分享出来,希望对初学者有所帮助。
          关于芯片的接法,只说三点,一个是写保护口wp,可以接在一个IO口上,写芯片前要拉低,如果不希望芯片内容被改变,就拉高。第二个是A1脚,也就是芯片的2脚。这是器件的地址选择脚,可以接VCC或地,对应器件地址不同,我的程序中是直接接地。有资料说该脚悬空与接地等效,我偷懒就没接。结果不稳定。所以最后还是接地了。第三是SCL与SDA线应接上拉电阻。我偷懒没接。把stc32g12k128内置的上拉电阻打开了,语句是P1PU=0x30;
    本例程提供了四个读写at24c1024的函数,下面分别介绍:
          一、页写函数
    void Page_Write(unsigned char addr,unsigned char SLAW)  /*  WordAddress,First Data Address,Byte lenth   */
    功能:向at24c1024写入一页数据
    参数1:SLAW-器件地址加页地址首位(P0);在A1脚接地时,常用的是两个值,0xa0和0xa2,分别表示芯片的前256页和后256页
    参数2:addr-器件的页地址,与参数1共同决定数据写入的位置,取值0-255间.
         这个函数很简洁好用,只是它在写入时要占用最前面的两个字节,分别写入的是上述两个参数值。在写入相对独立的数据,很方便,但写入大批量数据时,因每页插入了两个字节。所以读出时多了点麻烦。
         这个函数还有一个优点,是使用了IIC-DMA功能,运行时占用mcu时间少。有利提高mcu使用效率。
         二、随机写函数
    void WriteNbyte(unsigned int addr, unsigned char *p, unsigned int number,unsigned char SLAW)  //
    功能:向at24c1024指定地址写入数据。
    参数1:SLAW-与上一个函数相同,器件地址加页地址首位(P0);在A1脚接地时,常用的是两个值,0xa0和0xa2,分别表示芯片的前256页和后256页
    参数2:addr-这是个16位地址,高位是页地址,与前面的相同,低位是字节地址。这使得该函数能在任意位置写入内容。灵活方便。
    参数3:number-写入字节数,如果前面的字节地址是0的话,number最大可以是256.如果字节地址不是0,则number一般设的小与256,例字节地址是0x09(addr的低位),则number最大可以是246,如果超过这个数值,则地址到255后,写入的数据不是依次后延存储,而是反回本页地址0处开始存放。并依次向后存储。这不方便提取,也容易覆盖其它数据。(就是说芯片的地址指针不会自动跨页)
    参数4:p-这是缓冲区地址,在本例程中。写数据缓冲区使用的DmaTxBuffer[256],大了没用。在前面的页写函数中也需要用到这个缓冲区,只是默认是它。没有当参数写出来。
          三、随机读函数
    void ReadNbyte(unsigned int addr, unsigned char *p, unsigned int number,unsigned char SLAW)
    功能:读取指定地址处的数据
    参数1:SLAW-与前面的函数相同,表示芯片地址和区地址(分辨前256和后156页)
    参数2:addr-字节地址,16位的,与SLAW里的p0值共同决定要读的字节的具体地址
    参数3:number-本次读取的字节数,在读取数据时芯片的内部地址指针能不能自动跨页我没有试过。权当不能跨页使用,就是说每次调用读函数,读取的数据不超过256,原理与写函数类似。
    参数4:p-读缓冲区,本例程中用DmaRxBuffer[6400],虽然每次调用读函数,读取的数据不超过256字节,但在循环语句调用读函数时,如果缓冲区指针不复位,则可以继续依次向后存放读出的数据。所以我用了一个很大的缓冲区。减少向屏传送数据的次数。
        四、使用IIC-DMA的读函数
    void read_iicbydma(unsigned int addr,unsigned int number,unsigned char *p,unsigned char SLAW)
    这个函数的功能与参数与上一个相同,不做重复说明了。写这个函数是因为它使用了IIC-DMA功能,因而工作时对mcu的占用少。提高mcu使用效能。
    前面介绍的四个函数,两个基本读写,两个采用了IIC-DMA功能读写。比较一下发现论单任务完成速度,基本函数快些,但占用mcu时间多。
         为了展示前面四个函数的用法,又写了两个函数,一个往at24c1024里写入批量图像数据,一个从at24c1024里读出数据并送屏幕显示出来
    void transfer_image(unsigned int addr,unsigned char *p,unsigned char number_page,unsigned char SLAW)//向芯片送图像数据number_page是页数
    void disp_at24c1024(unsigned int x,unsigned int y,unsigned int addr,unsigned char number_page,unsigned char SLAW)//读出数据并送屏显示
          函数中x,y表示在屏上显示的起始位置,我把屏分成四份,用四个数组文件(pic01.h;pic02.h;pic03.h;pic04.h)放图像数据,显示屏为320x240。单个图的尺寸为160x100。这两个函数属于普通编程,不多说了。
         在规划at24c1024空间时,我在前区存入两个图像,其SLAW值为0xa0;在后区存入两个图像文件,其SLAW值为0xa2.在例程中可以注意一下。
    这里分区存放数据。没有选择连续存放,是考虑编程简单些。一个不常用的程序,写得复杂了没益处。
         下面是主程序:
    #include "STC32G.H"
    #include "mcu_initial.h"
    #include "tft_320_drv.h"
    #include "pic00.h"
    //#include "pic01.h"
    //#include "pic02.h"
    //#include "pic03.h"
    //#include "pic04.h"
    unsigned char extern xdata DmaRxBuffer[];
    unsigned char extern xdata DmaTxBuffer[];
    bit extern busy;
    //unsigned int cnt;
    void main(void)
    {
    mcu_initial();
      lcd_initial();
                    display_black();
    //因为内存空间有限,写图像数据进at24c1024时,分四次写入(两次也能行)每次打开一个写语句,并修改对应的头文件例pic01.h
            //transfer_image(0,pic01,125,0xa0);//从地址0x00开始,存入125页数据,打开时要有头文件pic01.h配合
            //transfer_image(32000,pic04,125,0xa0);//从地址32000开始,存入125页数据,打开时要有头文件pic04.h配合
       //transfer_image(32000,pic02,125,0xa2);//这是在后区。,打开时要有头文件pic02.h配合
        //transfer_image(0,pic03,125,0xa2);//这个也是后区,打开时要有头文件pic03.h配合
    disp_32x32(32,64,pin,red, yellow);//写入完成标志
          
    disp_at24c1024(0,0,0,125,0xa0);
            disp_at24c1024(160,100,32000,125,0xa0);
            disp_at24c1024(0,100,0,125,0xa2);
    disp_at24c1024(160,0,32000,125,0xa2);
    Delay10ms();
            display_image(0, 200,320,40,pic00);
            while(1);
    }
         运行时先分批打开写入数据函数,把图像数据写进芯片。就可以看到完整的图像显示了。
    考虑到写入速度比较慢。在写入时加了计数显示。能看到写入的进程。
         例程采用了lcm功能,lcm_dma功能和iic_dma功能。所以运行相关函数前要做好 相关设置,具体设置多数放在mcu_initial.c模式中了。少数在函数里。
          考虑到写at24c1024的速度可能比读慢些。所以读写函数采用了不同的iic速度设置。读程序时可以注意一下。主要是IIC_DMA页写时速度快了好像不行。所以用了230K,其它用了800k.
           附图是显示的图像效果和整机实况,看整机实况请不要仔细看,因为我的at24c1024芯片是用铁丝绑在洞洞板上,然后飞线连接的。老师看到会踢死我的。
          完整例程见附件,欢迎指点,欢迎吐槽。

    实际电路.jpg
    图像效果.jpg

    at24c1024_rd.zip

    308.44 KB, 下载次数: 56

    回复 送花

    使用道具 举报

    该用户从未签到

    550

    主题

    9209

    回帖

    1万

    积分

    管理员

    积分
    13926
    发表于 2023-2-26 18:20:30 | 显示全部楼层
    感谢奉献,还是要建议下,用 屠龙刀-STC32G12K128来做这个实验更方便

    1.png

    该用户从未签到

    550

    主题

    9209

    回帖

    1万

    积分

    管理员

    积分
    13926
    发表于 2023-2-26 18:23:33 | 显示全部楼层

    这有个为 OLED屏留的 I2C/SPI 接口
    1.png

    这有个为 OLED屏留的 I2C/SPI 接口

    该用户从未签到

    0

    主题

    9

    回帖

    350

    积分

    中级会员

    积分
    350
    发表于 2023-2-26 22:26:52 | 显示全部楼层
    楼主这是几寸的屏
  • TA的每日心情
    无聊
    2023-11-26 13:41
  • 签到天数: 1 天

    [LV.1]初来乍到

    14

    主题

    85

    回帖

    609

    积分

    高级会员

    积分
    609
     楼主| 发表于 2023-2-27 08:25:28 | 显示全部楼层
    2.4吋屏
    回复 送花

    使用道具 举报

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

    [LV.1]初来乍到

    14

    主题

    85

    回帖

    609

    积分

    高级会员

    积分
    609
     楼主| 发表于 2023-2-27 08:37:23 | 显示全部楼层
    神农鼎 发表于 2023-2-26 18:20
    感谢奉献,还是要建议下,用 屠龙刀-STC32G12K128来做这个实验更方便

    屠龙刀好强大,功能真不少。
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

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

    GMT+8, 2024-4-25 23:26 , Processed in 0.065609 second(s), 51 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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