×

STM32 FSMC驱动TFTLCD 难点解析资料下载

消耗积分:5 | 格式:pdf | 大小:176.27KB | 2021-04-10

胡秋阳

分享资料个

本篇文章三个主题:FSMC有关配置、一串字符显示原理、汉字显示原理。 一、FSMC的有关配置(博主用的是FSMC_A10): 来自别人家的博客 FSMC的介绍就不介绍了,网上一大片。我们就讨论讨论为什么用FSMC的地址线与TFTLCD的RS引脚相连?以及我们如何往LCD写数据/命令? FSMC称为可变静态存储控制器。可变:之所以称为“可变”,是由于通过对特殊功能寄存器的设置,FSMC 能够根据不同的外部存储器类型,发出相应的数据/地址/控制信号类型以匹配信号的速度。(这点很重要,后文会提到。) 简单说明一下吧~为什么不拿STM32的IO口直接接LCD的对应引脚?(看看我上边发的链接就清楚了),大致就是操作麻烦,效率低嘛。。好,FSMC是吧TFTLCD当成SRAM设备来用的,其操作时序和SRAM的控制完全类似,唯一不同的就是TFTLCD有RS信号,但是没有地址信号。 TFTLCD是通过RS信号来决定传送的数据是数据还是命令,本质上可以理解为一个地址信号,比如我们把RS接在A10上面(当然A0-Axx都可以)。那么LCD到底是怎么判断我们写的是命令还是数据呢?下面是重点!!! 以战舰的程序为例:: 这里因为数据线宽度是16位时,HADDR[25:1]->FSMC[24:0],相当于右移一位。下面是战舰给出的A10偏移量: 0x6c000000相比大家都没有问题。按理说A10的偏移量应该是2的11次方(0-10)=2048,转换为16进制就是800,那也比7FE大两位!(这里复习下基础知识:RS=0,写命令;RS=1,写数据。) 为什么呢?我是这么理解的(倒推法):按我的思路推,如果我们取LCD->LCD_REG的地址0x6c000800的话,当地址右移时,第10位就不是0了,而是1。对应RS=1,那么对于LCD就不是写命令了,而变成写数据了;又因为结构体内部成员对齐规则,LCD->LCD_RAM的地址就是0x6c00802了,当地址右移时,第10位也是1,对应RS=1。还是写数据!!!! 推到这应该明白了。如果按正常算法来计算的话,RS就只会等与1,就不会区分写命令和写数据了。 故我们要将A10的偏移量减去两位。就得到图中战舰的0x000007FE了。LCD->LCD_REG的地址就是0x6c0007FE了。当地址右移一位时第10位是0,对应RS=0,为对于LCD就是写命令了;而因为结构体内部成员对齐规则,LCD->LCD_RAM的地址就是0x6c000800了。当地址右移一位时第10位是1,对应RS=1,为对于LCD就是写数据了。这样FSMC就能区分传送的是数据还是命令了。。大功告成! 到这里,问题来了:我们就控制A10这一根线怎么就可以完成读写了呢?那些十多个引脚的电平又是谁在控制呢? 这个神秘的‘人物’就是上文我们提到的FSMC啦!先看一个战舰上的写寄存器函数: 第一个图:这里的LCD->LCD_REG是一个地址(0x6c000007FE),这里的寄存器序号哦:是指LCD手册里定义的寄存器地址。只要我们往LCD->LDC_REG这个地址里写一个变量(地址)。因为LCD->LDC_REG这个地址是FSMC管辖的。所以这时候FSMC就要勇敢的站出来管了~FSMC会自己生成相应的时序,包括CS、WR、RD和IO方向都是由FSMC控制!这就大大便利了我们对LCD的控制。 第二个图:这里的LCD->LCD_RAM也是一个地址(0x6c00000800),LCD->LCD_RAM=data;是往该寄存器地址里面写入数据。 二、一串字符的显示原理(战舰) 1、比如我们要显示一个字符串LCD_ShowString(x,x,x,"hello 21ic");x:是一些坐标哦和字体大小参数,先不管→_→ 2、那我们就得调用字符显示函数:LCD_ShowChar();来把一个字符的点阵全部取完。 3、字符是有点组成的,故在字符函数中不断调用画点函数LCD_DrawPoint();来画点(往LCD->LCD_RAM里写颜色值,这个颜色值在lcd.h里被定义为16位的地址)。 4、至此,在lcd_init()中有过LCD屏的初始化(设置显示参数),就可以显示了。 5、简析一下叠加和非叠加的原理吧→_→ 叠加就是字符点阵中是‘1’就用赋画笔颜色,是‘0’就赋背景颜色(那个字符的背景颜色,与全屏背景颜色无关),没毛病!因为最后显示的时候有个覆盖的作用。就是先把全屏颜色显示出来,再在全屏颜色的基础上覆盖上你的字符。所以就显示出叠加和非叠加(只有一个画笔颜色)了。 三、汉字显示原理 其实汉字显示和英文显示一个原理。很简单!显示的原理就是根据你的汉字字模字节大小来画点。 简单说说哈:大家都知道,字母的显示原理就是两个for循环(博主就知道这个),第一个for是控制‘行’的,第二个for是控制‘列’的。先给两个例子:比如显示一个16*08的字母,第一个for是循环16次,第二个for是循环8次;显示一个24*24的汉字,第一个for是循环72次,第二个for还是循环8次。不知道到这里大家看没看出来什么规律来→_→ 规律:第一个for是字模所占的字节数,第二个for是每次画8位(从列最高处往下描8个点),字符显示函数中间会有y-y0的字样,这是判断一列点数是否达到16或者24个了,是就x 1,换下一列。 总的来说,汉字的字模字节说就是比字母字模字节数大。修改的也就是第一个fo和y-y0里面的参数。 转自: (mbbeetchina)

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.obk20.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'STM32 FSMC驱动TFTLCD 难点解析资料下载',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.obk20.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);