OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 10548|回复: 16

串口DMA更新字库STM32F429

[复制链接]

16

主题

189

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1296
金钱
1296
注册时间
2013-8-27
在线时间
503 小时
发表于 2016-11-3 16:17:32 | 显示全部楼层 |阅读模式
本帖最后由 潜龙探渊 于 2016-11-3 16:45 编辑

最近工程上用到了LCD显示及W25Q256存储字库,硬件上就是没有SD卡,然后这就很困扰我怎么才能把字库放到外部FLASH里?


想来想去唯一的办法就是通过串口接收数据再把它烧到W25q256里面,然后我就先上论坛搜索有没有相关资料,然后搜了好久才找到一个“”这个帖子!(在这我要小小吐槽一下我们论坛的关键字搜索,感觉没有以前隔壁论坛的好用。需要你搜索的关键字要准确不支持模糊搜索,这就是我的个人使用感受不知道各位有没有同感的希望原子看到不要怪我八婆
     找到资料后当然就是开始吸收咯~这位群主的硬件是STM32F407的开发板而我手上又没有这个开发板,我现在手上就一个STM32F429的阿波罗开发板,我本来想仿照那位群主写的程序用HAL库仿写的,但是最后发现HAL跟407的标准库差太多了有些设置根本找不到,最后实在不行就改成用寄存器来仿写,反正寄存器操作无非就是多看芯片寄存器手册就可以了。
     仿写了二天终于写完了,但是调试还是遇到了各种问题,然后我就慢慢看他的程序思路然后再继续修改BUG,后面我就成功更新了一次!
成功了一次就继续测试发现,这个程序的下载成功率好像不高!!!又是用了一天的时间继续调程序BUG,后面终于把程序下载成功率提到了90%以上!
    然后我又把本来群主没有添加的32*32字体也给添加进去了,后面就只要把dma.c和dma.h、TXT文件烤到你工程目录下你也可以直接使用串口来更新字库了,可以造福没有SD卡的朋友们
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u8 chx,u32 par,u32 mar0,u32 mar1,u16 ndtr)
{
        DMA_TypeDef *DMAx;
        u8 streamx;
        
        USART1->CR3 |= 1<<6;                        //使能串口1的DMA接收
        if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
        {
                DMAx=DMA2;
                RCC->AHB1ENR|=RCC_AHB1ENR_DMA2EN;//DMA2时钟使能
        }else
        {
                DMAx=DMA1;
                 RCC->AHB1ENR|=RCC_AHB1ENR_DMA1EN;//DMA1时钟使能
        }
        while(DMA_Streamx->CR&0X01);        //等待DMA可配置
        
        streamx=(((u32)DMA_Streamx-(u32)DMAx)-0X10)/0X18;                 //得到stream通道号
         if(streamx>=6)DMAx->HIFCR|=0X3D<<(6*(streamx-6)+16);         //清空之前该stream上的所有中断标志
        else if(streamx>=4)DMAx->HIFCR|=0X3D<<6*(streamx-4);     //清空之前该stream上的所有中断标志
        else if(streamx>=2)DMAx->LIFCR|=0X3D<<(6*(streamx-2)+16);//清空之前该stream上的所有中断标志
        else DMAx->LIFCR|=0X3D<<6*streamx;                                                 //清空之前该stream上的所有中断标志

        DMA_Streamx->CR=0;                            //先全部复位CR寄存器值
        DMA_Streamx->AR=par;                         //DMA外设地址
        DMA_Streamx->M0AR=mar0;                 //DMA 存储器0地址
        DMA_Streamx->NDTR=ndtr;                         //数据传输量
        
        DMA_Streamx->CR|=0<<6;                        //外设到存储器模式
        DMA_Streamx->CR|=1<<8;                        //注意:这里设置为循环模式,不然不能启动第二次传输
        DMA_Streamx->CR|=0<<9;                        //外设非增量模式
        DMA_Streamx->CR|=1<<10;                        //存储器增量模式
        DMA_Streamx->CR|=0<<11;                        //外设数据长度:8位
        DMA_Streamx->CR|=0<<13;                        //存储器数据长度:8位
        DMA_Streamx->CR|=1<<16;                        //中等优先级
        DMA_Streamx->CR|=0<<21;                        //外设突发单次传输
        DMA_Streamx->CR|=0<<23;                        //存储器突发单次传输
        DMA_Streamx->CR|=(u32)chx<<25;  //通道选择
        DMA_Streamx->FCR=0<<2;                        //FIFO 模式禁止
        DMA_Streamx->FCR=0X03;                        //FIFO 阈值
        //使能DMA双缓冲模式
        DMA_Streamx->CR|=0<<19;                 //CT=0当前目标存储器为存储器0
        DMA_Streamx->M1AR=mar1;                        //DMA 存储器1地址
        DMA_Streamx->CR|=1<<18;                    //DBM=1设置双缓存模式
        
        //DMA_Streamx->CR|=1<<0;                //EN=1开启DMA传输
        DMA_Streamx->CR|=1<<4;                //使能DMA传输完成中断TCIE使能
        DMAx->HIFCR|=1<<11;                 //清除TCIF5中断标志
        //DMA NVIC 配置
        MY_NVIC_Init(3,2,DMA2_Stream5_IRQn,2);//组2,抢占2,优先级2 DMA2_Stream5_IRQn中断通道
        DMA_Streamx->CR|=1<<0;                //EN=1开启DMA传输
}
//重新开启一次DMA传输
//DMA_StreamxMA数据流,DMA1_Stream0~7/DMA2_Stream0~7
//ndtr:数据传输量  
void MYDMA_REST_Enable(DMA_Stream_TypeDef *DMA_Streamx,u32 par,u32 mar,u16 ndtr)
{
        DMA_Streamx->CR&=~(1<<0);         //关闭DMA传输
        while(DMA_Streamx->CR&0X1);        //确保DMA可以被设置  
        DMA_Streamx->AR=par;                //DMA外设地址
        DMA_Streamx->M0AR=mar;                 //DMA 存储器0地址
        DMA_Streamx->NDTR=ndtr;                //数据传输量
        DMA_Streamx->CR|=1<<0;                //开启DMA传输
}         

/********************************************************************
*函数名称:void DMA2_Stream5_IRQHandler(void)
*功    能MA2_Stream5_IRQHandler中断服务程序
*说    明MA2数据流5中断服务函数
*输入参数:无
*输出参数:无
*********************************************************************/  
void DMA2_Stream5_IRQHandler(void)                        
{
        if(DMA2->HISR&(1<<11))//判断TCIF5传输完成
        {
           DMA2->HIFCR|=1<<11; //清除TCIF5中断标志
           LED2=~LED2;
           //***************数据接收完处理******************//
           if(DMA2_Stream5->CR&(1<<19)) //得到CT当前目标存储器
           {
                        GBK_BUF_Flag=1; //存储器1
           }
           else
           {
                       GBK_BUF_Flag=0; //存储器0
           }
           //**************************************************//
        }
}
u8 updata_fontx(u16 x,u16 y,u8 size,u8 fx)
{
        u32 flashaddr=0;                                                                    
        u32 offx=0;      //接收到的文件大小
        u32 fsize=0;         //总文件大小
        u16 over_len =0; //最后数据长度
        
        switch(fx)
        {
                case 0:                                                                                                //更新UNIGBK.BIN
                        ftinfo.ugbkaddr=FONTINFOADDR+sizeof(ftinfo);        //信息头之后,紧跟UNIGBK转换码表
                        fsize=ftinfo.ugbksize=UNIGBK;                                        //UNIGBK大小
                        flashaddr=ftinfo.ugbkaddr;                                                //UNIGBK的起始地址
                        printf("lease send UNIGBK.bin\r\n");
                        break;
                case 1:
                        ftinfo.f12addr=ftinfo.ugbkaddr+ftinfo.ugbksize;        //UNIGBK之后,紧跟GBK12字库
                        fsize=ftinfo.gbk12size=GBK12_FONSIZE;                        //GBK12字库大小
                        flashaddr=ftinfo.f12addr;                                                //GBK12的起始地址
                        printf("lease send GBK12.FON\r\n");
                        break;
                case 2:
                        ftinfo.f16addr=ftinfo.f12addr+ftinfo.gbk12size;        //GBK12之后,紧跟GBK16字库
                        fsize=ftinfo.gbk16size=GBK16_FONSIZE;                        //GBK16字库大小
                        flashaddr=ftinfo.f16addr;                                                //GBK16的起始地址
                        printf("lease send GBK16.FON\r\n");
                        break;
                case 3:
                        ftinfo.f24addr=ftinfo.f16addr+ftinfo.gbk16size;        //GBK16之后,紧跟GBK24字库
                        fsize=ftinfo.gbk24size=GBK24_FONSIZE;                        //GBK24字库大小
                        flashaddr=ftinfo.f24addr;                                                //GBK24的起始地址
                        printf("lease send GBK24.FON\r\n");
                        break;
                case 4:
                        ftinfo.f32addr=ftinfo.f24addr+ftinfo.gbk24size;        //GBK24之后,紧跟GBK32字库
                        fsize=ftinfo.gbk32size=GBK32_FONSIZE;                        //GBK32字库大小
                        flashaddr=ftinfo.f32addr;                                                //GBK32的起始地址
                        printf("lease send GBK32.FON\r\n");
                        break;
        }
        fupd_prog(x,y,size,fsize,offx);                                 //进度显示
        GBK_BUF_Flag        = 2; //清除标志等待下一次DMA中断
        GBK_OVER_Flag        = 0; //停止计时
        printf("请发送文件...\r\n");
        do
        {
                if(GBK_OVER_Flag)GBK_OVER_Flag++;        //不为0开始计时
                if(GBK_BUF_Flag!=2)//判断是否进入DMA中断
                {               
                        LED0 = ~LED0;         //指示灯
                        GBK_OVER_Flag=1; //开始计时
                        if(GBK_BUF_Flag==0) //当前目标在存储器0
                        {
                                W25QXX_Write(Usart1_Rece_Buf1,offx+flashaddr,Usart1_DMA_Len);                //开始写入Usart6_DMA_Len个数据  
                        }
                        else
                        if(GBK_BUF_Flag==1) //当前目标在存储器0
                        {
                                W25QXX_Write(Usart1_Rece_Buf0,offx+flashaddr,Usart1_DMA_Len);                //开始写入Usart6_DMA_Len个数据  
                        }
                        offx+=Usart1_DMA_Len;         //加上已写完的数据量               
                        fupd_prog(x,y,size,fsize,offx);                                 //进度显示
                        GBK_BUF_Flag=2;                 //清除标志等待下一次DMA中断
                }               
                delay_us(100); //延时100us        
        }
        while(GBK_OVER_Flag<=WATE_TIME); //判断超时?
               
        over_len = Usart1_DMA_Len-DMA2_Stream5->NDTR; //最后数据长度        
        if(DMA2_Stream5->CR&(1<<19)) //得到CT当前目标存储器
        {
           W25QXX_Write(Usart1_Rece_Buf1,offx+flashaddr,over_len);//将DMA最后的一帧数据写入FLASH
        }
        else
        {
           W25QXX_Write(Usart1_Rece_Buf0,offx+flashaddr,over_len);//将DMA最后的一帧数据写入FLASH
        }
        offx+=over_len; //加上已写完的数据量
        fupd_prog(x,y,size,fsize,offx);                                 //进度显示
        //重新开启一次DMA传输
        MYDMA_REST_Enable(DMA2_Stream5,(u32)&USART1->DR,(u32)Usart1_Rece_Buf0,Usart1_DMA_Len);  //重置DMA
        printf("已写完数据,本次接收到%d字节!!!\r\n",offx);
        printf(" \r\n");
        delay_ms(100); //延时100ms
        if((offx > (fsize-1024))&(offx < fsize)) //误差在正负1K之内都认为是更新成功
                return 0; //更新成功
        else
                printf("更新失败,重新开始!\r\n");
                return 1; //更新失败
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------------还有我本想把最新的F429的芯片手册上传上去的,可是文件太大上传不了就算了~~~
还有各位如果你觉得我分享的程序有用,就来给我盖盖楼吧!让这个论坛活跃起来~~~~~~~~~~


里面的部分程序

里面的部分程序

字库丢失在擦除FALSH

字库丢失在擦除FALSH

擦除完就可以开始按照提示选择要发送的文

擦除完就可以开始按照提示选择要发送的文

选择放在工程目录下的字库

选择放在工程目录下的字库

已经烧写完一个字库

已经烧写完一个字库

继续烧写其他字库

继续烧写其他字库

全部字库更新完了

全部字库更新完了

串口DMA更新字库2016-11-03.rar

2.88 MB, 下载次数: 2373

字库在根目录下FOMT文件里

XCOM V2.0.rar

215.93 KB, 下载次数: 476

这个是我用的串口软件,没有的可下载

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2016-11-3 16:33:21 | 显示全部楼层
我就觉得这个MDK设置的好靓吖。
回复 支持 反对

使用道具 举报

16

主题

189

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1296
金钱
1296
注册时间
2013-8-27
在线时间
503 小时
 楼主| 发表于 2016-11-3 16:45:49 | 显示全部楼层
zuozhongkai 发表于 2016-11-3 16:33
我就觉得这个MDK设置的好靓吖。

我乱设的,是不是很亮
回复 支持 反对

使用道具 举报

80

主题

268

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
441
金钱
441
注册时间
2014-8-11
在线时间
84 小时
发表于 2016-11-22 15:35:11 | 显示全部楼层
  版主请问:DMA_Streamx->CR|=(u32)chx<<25;  //通道选择

这里的通道选择有没有问题,我觉得是DMA_Streamx->CR|=(u32)chx<<27;

在f429中文手册里usart1的接收dma   stream2和5都是在通道4上的,为何选择通道1???、
我是一只菜鸟,但我会大鹏展翅
回复 支持 反对

使用道具 举报

16

主题

189

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1296
金钱
1296
注册时间
2013-8-27
在线时间
503 小时
 楼主| 发表于 2016-11-23 09:02:25 | 显示全部楼层
战舰水手 发表于 2016-11-22 15:35
版主请问:DMA_Streamx->CR|=(u32)chx

其实这两种都可以正常使用啦~其实这两个就是二选一,你想用数据流2通道4也能正常使用,用数据流5通道4也行,反正只要是USART1_RX都行,看你怎么选择咯?
QQ图片20161123085744.png
回复 支持 反对

使用道具 举报

80

主题

268

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
441
金钱
441
注册时间
2014-8-11
在线时间
84 小时
发表于 2016-11-24 20:46:19 | 显示全部楼层
潜龙探渊 发表于 2016-11-23 09:02
其实这两种都可以正常使用啦~其实这两个就是二选一,你想用数据流2通道4也能正常使用,用数据流5通道4也 ...

DMA_Streamx->CR|=(u32)chx<<25; 的意义是通道的数字还是数据流的数字???
我是一只菜鸟,但我会大鹏展翅
回复 支持 反对

使用道具 举报

1

主题

12

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
408
金钱
408
注册时间
2016-2-15
在线时间
82 小时
发表于 2017-3-3 21:19:44 | 显示全部楼层
不错不错,谢谢楼主
回复 支持 反对

使用道具 举报

34

主题

283

帖子

0

精华

高级会员

Rank: 4

积分
739
金钱
739
注册时间
2015-11-15
在线时间
226 小时
发表于 2017-6-12 11:44:55 | 显示全部楼层
更新字库文件,直接将FONT文件,转换成TXT文件 ,在直接发送么?
与其感慨路难行,不如马上出发
回复 支持 反对

使用道具 举报

23

主题

344

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2312
金钱
2312
注册时间
2017-7-6
在线时间
280 小时
发表于 2017-7-14 09:34:22 | 显示全部楼层
论坛搜索不支持模糊化的方式确实很蛋疼,希望改进。
回复 支持 反对

使用道具 举报

2

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
149
金钱
149
注册时间
2013-9-14
在线时间
36 小时
发表于 2017-8-28 17:37:50 | 显示全部楼层
请问下 XBF字体怎么更新 ?
回复 支持 反对

使用道具 举报

0

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
65
金钱
65
注册时间
2019-8-24
在线时间
26 小时
发表于 2019-10-23 14:01:32 | 显示全部楼层
字体这样更新后乱码
回复 支持 反对

使用道具 举报

2

主题

9

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2016-11-10
在线时间
7 小时
发表于 2019-12-12 11:55:54 | 显示全部楼层
不错的,可以看看
回复 支持 反对

使用道具 举报

0

主题

10

帖子

0

精华

新手上路

积分
34
金钱
34
注册时间
2020-2-7
在线时间
8 小时
发表于 2020-3-17 23:41:34 | 显示全部楼层
谢谢分享
回复 支持 反对

使用道具 举报

8

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
98
金钱
98
注册时间
2019-5-29
在线时间
28 小时
发表于 2020-11-3 14:45:15 | 显示全部楼层
楼主,我想问一下这种方式用STM32F103能实现么,我看DMA设置的命令名字不是很一样,多了一些库函数,可以用自写的逻辑代替么
回复 支持 反对

使用道具 举报

16

主题

189

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1296
金钱
1296
注册时间
2013-8-27
在线时间
503 小时
 楼主| 发表于 2020-12-15 09:49:47 | 显示全部楼层
a524660466 发表于 2020-11-3 14:45
楼主,我想问一下这种方式用STM32F103能实现么,我看DMA设置的命令名字不是很一样,多了一些库函数,可以用 ...

应该可以的,DMA只是数据快速搬运的一种方法
回复 支持 反对

使用道具 举报

4

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
100
金钱
100
注册时间
2019-7-8
在线时间
22 小时
发表于 2021-2-8 15:31:03 | 显示全部楼层
在第一个文件就一直失败怎么回事
回复 支持 反对

使用道具 举报

4

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
100
金钱
100
注册时间
2019-7-8
在线时间
22 小时
发表于 2021-2-8 15:35:58 | 显示全部楼层

回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-14 03:59

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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