所有资料打包下载:
http://www.51hei.com/bbs/dpj-57024-1.html
下面是部分内容预览:
随着控制理论和电子技术的发展,控制芯片的发展可谓速度迅猛。从当初风靡业界的51单片机,到如今dsp、fpga、arm等等的百花齐放,这无不印证的控制处理器芯片发展的强大动力。而stm32芯片(st:意法半导体公司;m:cortex-m系列芯片;32:32位芯片)由于其具有优秀的运算速度和丰富的芯片资源以及低廉的价格(低至1美元)已经渐渐取代单片机。
Stm32对比起单片机,不仅仅运算速度几十倍之差,而且对于其丰富的内部资源(例如一般STM均集成多路ADC、DAC、DMA、多路IIC、多路UART、SPI等等众多功能)单片机是无法匹敌的。而且stm芯片已经越来越接近单片机价格。众多优秀的表现可以看出stm32将取代单片机。 本次作品的原理是通过以STM32芯片作为主控芯片,通过利用STM32芯片自带的AD功能实时识别信号源的电压,并且以一定的采样周期采样电压数据,并按照队列方式储存芯片当中。再通过4.2英寸的显示屏把波形实时地显示出来。即可完成功能的实现。
引 言 由于传统示波器虽然功能齐全但是体积旁大,不方便携带,本设计针对这种缺点设计一种体积小、成本低、功耗小、便携数字示波器,同时达到学以致用,理论和实践相结合,进一步学习课外知识,培养综合应用知识,锻炼动手和实际工作的能力。示波器实现输入频率范围为20HZ—1KHZ,幅度范围为0V—+3.26V(由于时间和元件关系只能做到这一量程,换上带有vref-和vref+的stm芯片即可做出正负电压检测的功能),实现波形实时显示以及幅度测量。示波器在电子、电气、控制等领域应用十分广泛,随着计算机的发展,示波器已经实现了和计算机互联,共享数据,但现有示波器有诸多不足,体积庞大,价格昂贵,功能齐全的示波器在某些场合并不能得到充分的应用。本课题所研究的示波器定位于抵挡型,即在性能上满足大多场合的需要,努力实现小型化,价格低廉,携带方便,这样在财力有限的小用户能够普及,并和功能齐全高档示波器配合使用,取长补短。本设计的硬件设计简洁,结构明了,而且体积细小,非常方便携带。而且电池采用可充电大容量镍镉电池,可使用时间长。本设计对信号的采样,使用实时采样方式和有限的数据队列储存方式存储,这种方法的优点是,设计相对简单,能实时显示所测信号的波形。缺点是,由于受AD转换速率的限制不能测量频率很高的信号。另外,AD只能测量范围很小的电压信号,单输入信号可能更小,或者更大,所以要对信号进行程控放大和衰减。由于本设计时间和元件有限,只能做出检测0到3.26v的示数。只要在信号输入处加上加法电路改变量程或者把stm32f103c8t6芯片换成stm32f103vct6(带vref+和vref-)即可。
第一章 系统整体概述 从任务的要求分析,主要包括的内容为电压的实时测量和采集,通过stm32f103c8t6控制,运用算法描绘成连续曲线,在4.2英寸液晶显示屏上显示出来。 整体设计思路:stm32的PA0~PA7与4.2英寸液晶屏的8个数据位通信,通过PB8、PB9,、PB10、PB11分别控制液晶屏的RST、CS、RS、WR、液晶屏的RD接3.3v来控制液晶屏的显示。通过PB0输入信号进行信号采集。PB1为暂停键,方便暂停波形观测波形。PB7和PB4分别为增大网格时间间隔和减少网格时间间隔。 系统如下图1.1:
图1.1 系统图 本设计使用方法: - 把电路板背面的电池盒开关由OFF拨去ON,即可进入波形显示界面。
- 如果暂停键没有按下,信号输入插针的地接信号器的地线,IN接信号输入。即可有输出波形显示到显示屏上。
- 网格横向方向有时间轴,纵轴为电压值,电压纵轴已有标注,而横轴时间的每一个网格间隔相距的时间间隔在显示屏的右上方已经显示出来。
- 通过按按键T+或者T-即可改变横轴每个网格之间的时间间隔。
- 按下暂停键即可得到暂停在一个时间点的波形。再按一次暂停键又可继续观察实时的波形。
第二章 硬件电路的设计
2.1STM32最小系统介绍 STM32系列基于专为要求高性能、低成本、低功耗的嵌入式应用专门设计的ARM Cortex-M3内核。按性能分成两个不同的系列:STM32F103“增强型”系列和STM32F101“基本型”系列。增强型系列时钟频率达到72MHz,是同类产品中性能最高的产品;基本型时钟频率为36MHz,以16位产品的价格得到比16位产品大幅提升的性能,是16位产品用户的最佳选择。两个系列都内置32K到128K的闪存,不同的是SRAM的最大容量和外设接口的组合。时钟频率72MHz时,从闪存执行代码,STM32功耗36mA,是32位市场上功耗最低的产品。 本设计所用的STM32F103C8T6集成的片上功能如下: (1) 1.2v内核供电,1.8V/2.5V/3.3/V存储器供电,3.3V外部I/O供电 (2) 外部存储控制器 (3) LCD 控制器 (4) 4通道DNA并有外部请求引脚 (5) 3通道UART电子技术综合实践 (5) 3通道UART (6) 2通道SPI (7) 1通道IIC总线接口1通道IIS总线接口 (8) AC’97编解码器接口 (9) 兼容SD主接口协议1.0版和MMC卡协议2.11兼容版 (10) 2通道USB主机1通道USB设备 (11) 4通道PWM定时器和1通道内部定时器/看门狗定时器 (12) 8通道10位ADC和触摸屏接口 (13) 80个通用I/O和24通道外部中断源 而本次使用的是STM32F103C8T6是已经集成好的最小系统板如下图:
图2.1.1 STM32F103C8T6最小系统实物图
图2.1.2 STM32F103C8T6最小系统电路图 2.2 、4.2英寸TFT液晶显示屏 尺寸:320*400;
图2.2 4.2英寸液晶显示屏图片 2.3电源设计:虽然stm32是低功耗芯片,可以因为4.2英寸液晶屏是高功耗器件,所以在电源的选择上,我选择了四个可充电的1000mah的1.2v镍镉电池串联起来提供4.8v作为供电电源,工作续航能力得到大大提高。 图2.2 电池盒 附:实物效果图一张:
51开发板作为波形发生器 正弦波、三角波、梯形波、正弦波
软件的任务包括通过初始化GPIO、RCC、ADC、 SYSTICK、EXIT、NVIC、4.2英寸液晶屏等进行初始化。然后通过AD采集的信号以队列方式储存起来,再输送到液晶屏。当完成了一个屏幕的数据点采集,再从头开始消点、采集、画点,当然在写程序的时候加入了一个使数据点连在一起的小算法达到显示效果。 所编写程序如下:(以下为主要程序,其他次要程序文件均在附录中)
通过无数的错误与更正,总结如下几点特别需要注意的要点: - 由于本人设计的显示方式的横向显示,所以在字符取模的时候要注意要横向取模。其中,取模软件zimo221。
2、经过很多次调试,已经搞清楚本程序编写液晶屏颜色参数时,24位颜色参数格式为G-R-B,其中G、R、B各用一个8位数据表示。而颜色表数据也比较难找。我的微博中有转发过有关颜色RGB混合参数的非常实用的微博。详情请关注新浪微博@中南大学陈锦熙。 3、 以下程序为调试多天之后能最终成功的“消点-采点-画点”的程序,也是本设计的核心程序。其中加入了让采集点连续起来的小算法,参考自百度的资料。曾试过在每一次采集结束时通过for(mm=0;mm<400;mm++)adre[mm]=ad[mm];使ad[mm]为实时数据,adre[mm]为上一轮数据。利用adre[mm]在下一轮消点(包括连续算法的连线),但是调试过几天发现adre[mm]=ad[mm]得到的的数据竟然是乱值。所以在调试程序时必须要灵活变通,敢于怀疑。 if(clr_flag==1) //清点 { draw_point(allnum + move_x ,ad[allnum]+ move_y,0x0000); if((allnum<=398)&&(ad[allnum+1]>ad[allnum])) for(nn=ad[allnum+1]-ad[allnum];nn>0;nn--) draw_point(allnum +1+ move_x ,ad[allnum+1]-nn+move_y,0x0000); if((allnum<=398)&&(ad[allnum+1]0;nn--) draw_point(allnum +1+ move_x ,ad[allnum+1]+nn+move_y,0x0000); } ad[allnum]=ADC_GetConversionValue(ADC1)/30; //取值画图 draw_point(allnum + move_x ,ad[allnum]+ move_y,0xffc000); if((allnum>=1)&&(ad[allnum]>ad[allnum-1])) for(nn=ad[allnum]-ad[allnum-1];nn>0;nn--) draw_point(allnum + move_x ,ad[allnum]-nn+move_y,0xffc000); if((allnum>=1)&&(ad[allnum]0;nn--) draw_point(allnum + move_x ,ad[allnum]+nn+move_y,0xffc000); allnum++; 4、做按键程序的时候,打算用中断做,可是全局变量定义总是出错。克服了这个问题之后,发现芯片用PB3做中断按键时运作失败。通过多次的调试,发现PB3总是为低电平。换了芯片之后情况一样。所以换做PB4、PB7作为中断按键。而PB1作为常开/常闭开关用来暂停波形。最后得到了应有效果。 5、关于4.2英寸液晶屏的调解程序,复杂度相当高。而且大部分指令都难以理解。连说明书都只有英文版的。所以在此我已经在本次工程的4.2寸液晶屏c文件中用中文注释了所有命令的中文功能。便于自己理解,也可以帮助大家的学习液晶屏这一个优秀的输出平台。
通过这次基于STM32的微型掌上示波器的设计,我更加深入地理解和运用到了更多关于ARM尤其是STM32的特点和功能。 在之前我也用过51做温度器、做霍尔元件测速器、振动报警器、用过stm32做水力发电叶片、风力发电叶片控制电路(比赛作品)。但这次示波器的设计断断续续耗计了我三个星期,是我学习到最多的一次。因为这次设计涉及到的AD、和42英寸液晶屏都是STM32的中端应用。其实这个设计如果用COSII来做的话应该能达到更丰富的效果。 STM32F103C8T6的参考正、负电压默认连接到芯片工作电压3.3V(实际3.26V)和地(0V)。所以示波器检测的电压区间只能为0~3.26V。如果要实现负电压的检测,则要加入加法电路。市面上的STM32F103C8T6升级版STM32F103VCT6有AD对应的的VREF+和VREF-接口,可以完美地解决这个问题。 这次没有用PCB板做,是因为芯片用的是最小系统集成板,显示屏用的是ili9325和液晶板的集成板,核心器件已经是高度集成化的,连接电路比较简单,所以选用了较为简便的洞洞板来拼接这两个模块。 因为没有昂贵的函数发生器,而且去物理院借用函数发生器非常麻烦,所以我用51单片机开发板做出来了简易函数发生器(能产生矩形波、三角波、锯齿波、正弦波,用独立按键1、2、3、4控制)。程序在附录中。 这次的作品需要改进的地方有很多: 1、运用多路AD即可做出多踪示波器,这个很容易实现。 2、可以做储存数据的程序; 3、可以做成触屏,使用界面更加友好; 4、用UCOSII做可能有更佳的效果。 总之,通过这次作品设计,我撞到了数不清的困难和到现在解不开的难题。可以有困难就去克服,克服不了就寻求网络资源帮忙。如果实在解不开,就用另一种方法代替。虽然“写程序用了三个小时,调试用了三天。”可是坚持下去,我得到的是锻炼和经验。这个设计有很多废命令和不太合理、累赘的地方,还望大家指正! 附录一 字库(本程序适用) - // ------------------ 汉字字模的数据结构定义 ------------------------ //
- struct typFNT_GB16 // 汉字字模数据结构
- {
- unsigned char Index[3]; // 汉字内码索引
- unsigned char Msk[32]; // 点阵码数据
- };
-
- /////////////////////////////////////////////////////////////////////////
- // 汉字字模表 //
- // 汉字库: 宋体16.dot,横向取模左高位,数据排列:从左到右从上到下 // (原来为横向不倒序)
- /////////////////////////////////////////////////////////////////////////
- const struct typFNT_GB16 codeGB_16[] = // 数据表
- {
- /*-- 文字: 简 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "简",0x00,0x08,0x00,0x04,0xFF,0xC3,0x00,0x12,0x00,0x26,0x3F,0x8A,0x24,0xA2,0x24,0xAA,
- 0x24,0xA4,0x3F,0xA3,0x00,0x22,0x80,0x26,0xFF,0xEA,0x00,0x02,0x00,0x02,0x00,0x00,
- /*-- 文字: 易 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "易",0x00,0x00,0x08,0x00,0x04,0x00,0x42,0x00,0x23,0x7F,0x12,0xC9,0x8E,0x49,0x42,0x49,
- 0x32,0x49,0x0E,0x49,0x42,0x49,0x82,0x7F,0x42,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,
- /*-- 文字: 示 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "示",0x20,0x40,0x10,0x40,0x08,0x42,0x06,0x42,0x00,0x42,0x40,0x42,0x80,0x42,0x7F,0xC2,
- 0x00,0x42,0x00,0x42,0x00,0x42,0x02,0x42,0x04,0x42,0x08,0x40,0x30,0x40,0x00,0x00,
- /*-- 文字: 波 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "波",0x04,0x10,0x04,0x60,0x7C,0x02,0x03,0x0C,0x80,0xC0,0x60,0x00,0x1F,0xF8,0x80,0x88,
- 0x43,0x88,0x2C,0x88,0x10,0xFF,0x28,0x88,0x46,0x88,0x81,0xA8,0x80,0x18,0x00,0x00,
- /*-- 文字: 器 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "器",0x08,0x80,0x08,0x80,0xF4,0x9E,0x94,0x92,0x92,0x92,0x92,0x92,0xF1,0x9E,0x00,0xE0,
- 0x01,0x80,0xF2,0x9E,0x92,0xB2,0x94,0xD2,0x94,0x92,0xF8,0x9E,0x08,0x80,0x00,0x00,
- /*-- 文字: 时 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "时",0x00,0x00,0x3F,0xFC,0x10,0x84,0x10,0x84,0x10,0x84,0x3F,0xFC,0x00,0x00,0x00,0x10,
- 0x01,0x10,0x06,0x10,0x40,0x10,0x80,0x10,0x7F,0xFF,0x00,0x10,0x00,0x10,0x00,0x00,
- /*-- 文字: 间 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "间",0x00,0x00,0xFF,0xF8,0x00,0x01,0x00,0x06,0x00,0x00,0x1F,0xF0,0x11,0x12,0x11,0x12,
- 0x11,0x12,0x1F,0xF2,0x00,0x02,0x40,0x02,0x80,0x02,0x7F,0xFE,0x00,0x00,0x00,0x00,
- /*-- 文字: 隔 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "隔",0x00,0x00,0xFF,0xFE,0x04,0x22,0x08,0x5A,0x07,0x86,0x00,0x00,0xFF,0x02,0x09,0x7A,
- 0x0B,0x4A,0x0D,0x4A,0x79,0x4A,0x0D,0x4A,0x4B,0x4A,0x89,0x7A,0x7F,0x02,0x00,0x00,
- /*-- 文字: 0 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
- "0",0x00,0x00,0x0F,0xE0,0x10,0x10,0x20,0x08,0x20,0x08,0x10,0x10,0x0F,0xE0,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- /*-- 文字: 1 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
- "1",0x00,0x00,0x20,0x10,0x20,0x10,0x3F,0xF8,0x20,0x00,0x20,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- /*-- 文字: 2 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
- "2",0x00,0x00,0x30,0x70,0x28,0x08,0x24,0x08,0x22,0x08,0x21,0x88,0x30,0x70,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- /*-- 文字: 3 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
- "3",0x00,0x00,0x18,0x30,0x20,0x08,0x20,0x88,0x20,0x88,0x11,0x48,0x0E,0x30,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- /*-- 文字: 4 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
- "4",0x00,0x00,0x07,0x00,0x04,0xC0,0x24,0x20,0x24,0x10,0x3F,0xF8,0x24,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- /*-- 文字: 5 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
- "5",0x00,0x00,0x19,0xF8,0x21,0x08,0x20,0x88,0x20,0x88,0x11,0x08,0x0E,0x08,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- /*-- 文字: 6 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
- "6",0x00,0x00,0x0F,0xE0,0x11,0x10,0x20,0x88,0x20,0x88,0x11,0x18,0x0E,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- /*-- 文字: 7 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
- "7",0x00,0x00,0x00,0x38,0x00,0x08,0x3F,0x08,0x00,0xC8,0x00,0x38,0x00,0x08,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- /*-- 文字: 8 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
- "8",0x00,0x00,0x1C,0x70,0x22,0x88,0x21,0x08,0x21,0x08,0x22,0x88,0x1C,0x70,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- /*-- 文字: 9 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
- "9",0x00,0x00,0x00,0xE0,0x31,0x10,0x22,0x08,0x22,0x08,0x11,0x10,0x0F,0xE0,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- /*-- 文字: M --*/
- /*-- 宋体14; 此字体下对应的点阵为:宽x高=10x19 --*/
- "M",0x20,0x08,0x3F,0xF8,0x00,0xF8,0x3F,0x00,0x00,0xF8,0x3F,0xF8,0x20,0x08,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- /*-- 文字: S --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
- "S",0x00,0x00,0x38,0x70,0x20,0x88,0x21,0x08,0x21,0x08,0x22,0x08,0x1C,0x38,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- /*-- 调入了一幅图像:这是您新建的图像 --*/
- /*-- 宽度x高度=16x16 --*/
- "花",0x00,0x80,0x00,0x40,0x00,0x20,0x03,0x10,0x03,0x10,0x00,0x20,0x00,0x40,0x00,0x80,
- 0x01,0x00,0x02,0x00,0x04,0x00,0x08,0xC0,0x08,0xC0,0x04,0x00,0x02,0x00,0x01,0x00,
-
- /*-- 文字: 陈 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "陈",0x00,0x00,0xFF,0xFE,0x04,0x22,0x08,0x5A,0x07,0x86,0x20,0x08,0x11,0x88,0x0D,0x68,
- 0x41,0x18,0x81,0x0F,0x7F,0xE8,0x01,0x08,0x05,0x08,0x09,0x08,0x30,0x08,0x00,0x00,
- /*-- 文字: 锦 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "锦",0x01,0x20,0x01,0x10,0x01,0x2C,0x7F,0xE7,0x21,0x24,0x11,0x24,0x3E,0x00,0x02,0x7C,
- 0x02,0x54,0x02,0x56,0xFF,0xD5,0x02,0x54,0x12,0x54,0x22,0x7C,0x1E,0x00,0x00,0x00,
- /*-- 文字: 熙 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "熙",0x80,0x00,0x47,0xFE,0x34,0x02,0x04,0xF2,0x04,0x92,0x17,0x9E,0x64,0x92,0x04,0xF2,
- 0x14,0x00,0x63,0xFE,0x04,0x22,0x04,0x22,0x14,0x22,0xE4,0x3E,0x07,0x00,0x00,0x00,
- /*-- 文字: 中 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "中",0x00,0x00,0x00,0x00,0x0F,0xF0,0x04,0x10,0x04,0x10,0x04,0x10,0x04,0x10,0xFF,0xFF,
- 0x04,0x10,0x04,0x10,0x04,0x10,0x04,0x10,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,
- /*-- 文字: 南 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "南",0x00,0x04,0xFF,0xE4,0x00,0x24,0x08,0x24,0x09,0x64,0x09,0xA4,0x09,0x24,0x7F,0x3F,
- 0x09,0x24,0x09,0xA4,0x09,0x64,0x48,0x24,0x80,0x24,0x7F,0xE4,0x00,0x04,0x00,0x00,
- /*-- 文字: 大 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "大",0x80,0x20,0x80,0x20,0x40,0x20,0x20,0x20,0x10,0x20,0x0C,0x20,0x03,0x20,0x00,0xFF,
- 0x03,0x20,0x0C,0x20,0x10,0x20,0x20,0x20,0x40,0x20,0x80,0x20,0x80,0x20,0x00,0x00,
- /*-- 文字: 学 --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "学",0x04,0x40,0x04,0x30,0x04,0x11,0x04,0x96,0x04,0x90,0x44,0x90,0x84,0x91,0x7E,0x96,
- 0x06,0x90,0x05,0x90,0x04,0x98,0x04,0x14,0x04,0x13,0x04,0x50,0x04,0x30,0x00,0x00,
- /*-- 文字: --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "暂",0x00,0x82,0x01,0x9A,0x00,0x96,0xFE,0x93,0x93,0xFA,0x92,0x52,0x93,0x52,0x92,0x80,
- 0x92,0x7E,0x92,0x12,0x92,0x12,0xFE,0x12,0x03,0xF1,0x00,0x11,0x00,0x10,0x00,0x00,
- /*-- 文字: --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
- "停",0x00,0x80,0x00,0x60,0xFF,0xF8,0x00,0x07,0x03,0x00,0x01,0x04,0x05,0x74,0x45,0x54,
- 0x85,0x55,0x7D,0x56,0x05,0x54,0x05,0x54,0x05,0x74,0x01,0x04,0x03,0x00,0x00,0x00,
- /*-- 文字: . --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
- ".",0x00,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- /*-- 文字: V --*/
- /*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
- "V",0x00,0x08,0x00,0x78,0x07,0x88,0x38,0x00,0x0E,0x00,0x01,0xC8,0x00,0x38,0x00,0x08,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- };
复制代码
附录二 51单片机波形发生器(本程序适用)
其中独立按键1、2、3、4按下时会产生四个不同波形(矩形、三角波、梯形波、正弦波)
主函数:
Main.c
- #include
- #include "i2c.h"
- #define AddWr 0x90 //写数据地址
- #define AddRd 0x91 //读数据地址
-
- /*unsigned char code tab[]={
- 0,25,50,75,100,125,150,175,200,225,250 //表格数值越多,波形越平滑
- };*/
- unsigned char code tab1[]={
- 0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,
- 170,180,190,200,210,220,230,240,250
- };
- unsigned char code juchi[64]={
- 0,4,8,12,16,20,24,28,32,36,40,45,49,53,57,61,65,69,73,77,81,85,89,93,97,101,105,109,113,117,121,125,130,134,138,142,
- 146,150,154,158,162,166,170,174,178,182,186,190,194,198,202,206,210,215,219,223,227,231,235,239,243,247,251,255
- };
-
- unsigned char code sin[64]={135,145,158,167,176,188,199,209,218,226,234,240,245,249,252,254,254,253,251,247,243,237,230,222,213,204,193,182,170,158,
- 146,133,121,108,96,84,72,61,50,41,32,24,17,11,7,3,1,0,0,2,5,9,14,20,28,36,45,55,66,78,90,102,114,128};
- unsigned char code sanjiao[64]={
- 0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,
- 248,240,232,224,216,208,200,192,184,176,168,160,152,144,136,128,120,112,104,96,88,80,72,64,56,48,40,32,24,16,8,0
- };
- unsigned char code tixing[64]={
- 0,13,26,39,52,65,78,91,104,117,130,143,156,169,182,195,208,221,234,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,
- 247,247,247,247,247,247,247,242,229,216,203,190,177,164,151,138,125,112,99,86,73,60,47,34,21,8
- };
- unsigned char code juxing[64]={
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- };
-
-
-
-
- extern bit ack;
- bit WriteDAC(unsigned char dat,unsigned char num);
- /*------------------------------------------------
- 主程序
- ------------------------------------------------*/
- main()
- {
- unsigned char i;
- while (1) //主循环
- {
- // for(i=0;i<26;i++)
- // WriteDAC(tab1[i],1);
- while(P1==0xff)
- {
- for(i=0;i<64;i++)
- WriteDAC(juxing[i]*6/10,1);
- if(P1!=0xff)break;
- }
- while(P1==0xfe)
- {
- for(i=0;i<64;i++)
- WriteDAC(tixing[i]*6/10,1);
- if(P1!=0xfe)break;
- }
- while(P1==0xfd)
- {
- for(i=0;i<64;i++)
- WriteDAC(sanjiao[i]*6/10,1);
- if(P1!=0xfd)break;
- }
- while(P1==0xfb)
- {
- for(i=0;i<64;i++)
- WriteDAC(sin[i]*6/10,1);
- if(P1!=0xfb)break;
- }
- while(P1==0xf7)
- {
- for(i=0;i<64;i++)
- WriteDAC(juchi[i]*6/10,1);
- if(P1!=0xf7)break;
- }
- }
- }
-
- /*------------------------------------------------
- 写入DA转换数值
- 输入参数:dat 表示需要转换的DA数值,范围是0-255
- ------------------------------------------------*/
- bit WriteDAC(unsigned char dat,unsigned char num)
- { unsigned char i;
- Start_I2c(); //启动总线
- SendByte(AddWr); //发送器件地址
- if(ack==0)return(0);
- SendByte(0x40); //发送器件子地址
- if(ack==0)return(0);
- for(i=0;i<num;i++)
- {
- SendByte(dat); //发送数据
- if(ack==0)return(0);
- }
- Stop_I2c();
-
- }
-
-
- IIC协议:
- IIC.C
-
-
-
- #include "i2c.h"
-
- #define _Nop() _nop_() //定义空指令
-
- bit ack; //应答标志位
-
- sbit SDA=P2^1;
- sbit SCL=P2^0;
-
- /*------------------------------------------------
- 启动总线
- ------------------------------------------------*/
- void Start_I2c()
- {
- SDA=1; //发送起始条件的数据信号
- _Nop();
- SCL=1;
- _Nop(); //起始条件建立时间大于4.7us,延时
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- SDA=0; //发送起始信号
- _Nop(); //起始条件锁定时间大于4μ
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- SCL=0; //钳住I2C总线,准备发送或接收数据
- _Nop();
- _Nop();
- }
- /*------------------------------------------------
- 结束总线
- ------------------------------------------------*/
- void Stop_I2c()
- {
- SDA=0; //发送结束条件的数据信号
- _Nop(); //发送结束条件的时钟信号
- SCL=1; //结束条件建立时间大于4μ
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- SDA=1; //发送I2C总线结束信号
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- }
-
-
-
-
- /*----------------------------------------------------------------
- 字节数据传送函数
- 函数原型: void SendByte(unsigned char c);
- 功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
- 此状态位进行操作.(不应答或非应答都使ack=0 假)
- 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
- ------------------------------------------------------------------*/
- void SendByte(unsigned char c)
- {
- unsigned char BitCnt;
-
- for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位
- {
- if((c<<bitcnt)&0x80)sda=1; 判断发送位
- else SDA=0;
- _Nop();
- SCL=1; //置时钟线为高,通知被控器开始接收数据位
- _Nop();
- _Nop(); //保证时钟高电平周期大于4μ
- _Nop();
- _Nop();
- _Nop();
- SCL=0;
- }
-
- _Nop();
- _Nop();
- SDA=1; //8位发送完后释放数据线,准备接收应答位
- _Nop();
- _Nop();
- SCL=1;
- _Nop();
- _Nop();
- _Nop();
- if(SDA==1)ack=0;
- else ack=1; //判断是否接收到应答信号
- SCL=0;
- _Nop();
- _Nop();
- }
-
-
-
-
-
-
-
- /*----------------------------------------------------------------
- 字节数据传送函数
- 函数原型: unsigned char RcvByte();
- 功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
- 发完后请用应答函数。
- ------------------------------------------------------------------*/
- /*unsigned char RcvByte()
- {
- unsigned char retc;
- unsigned char BitCnt;
-
- retc=0;
- SDA=1; //置数据线为输入方式
- for(BitCnt=0;BitCnt<8;BitCnt++)
- {
- _Nop();
- SCL=0; //置时钟线为低,准备接收数据位
- _Nop();
- _Nop(); //时钟低电平周期大于4.7us
- _Nop();
- _Nop();
- _Nop();
- SCL=1; //置时钟线为高使数据线上数据有效
- _Nop();
- _Nop();
- retc=retc<<1;
- if(SDA==1)retc=retc+1; //读数据位,接收的数据位放入retc中
- _Nop();
- _Nop();
- }
- SCL=0;
- _Nop();
- _Nop();
- return(retc);
- }
- */
-
-
- /*----------------------------------------------------------------
- 应答子函数
- 原型: void Ack_I2c(void);
-
- ----------------------------------------------------------------*/
- /*void Ack_I2c(void)
- {
-
- SDA=0;
- _Nop();
- _Nop();
- _Nop();
- SCL=1;
- _Nop();
- _Nop(); //时钟低电平周期大于4μ
- _Nop();
- _Nop();
- _Nop();
- SCL=0; //清时钟线,钳住I2C总线以便继续接收
- _Nop();
- _Nop();
- }*/
- /*----------------------------------------------------------------
- 非应答子函数
- 原型: void NoAck_I2c(void);
-
- ----------------------------------------------------------------*/
- /*void NoAck_I2c(void)
- {
-
- SDA=1;
- _Nop();
- _Nop();
- _Nop();
- SCL=1;
- _Nop();
- _Nop(); //时钟低电平周期大于4μ
- _Nop();
- _Nop();
- _Nop();
- SCL=0; //清时钟线,钳住I2C总线以便继续接收
- _Nop();
- _Nop();
- }
-
- */
-
-
-
-
- /*----------------------------------------------------------------
- 向无子地址器件发送字节数据函数
- 函数原型: bit ISendByte(unsigned char sla,ucahr c);
- 功能: 从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.
- 如果返回1表示操作成功,否则操作有误。
- 注意: 使用前必须已结束总线。
- ----------------------------------------------------------------*/
- /*bit ISendByte(unsigned char sla,unsigned char c)
- {
- Start_I2c(); //启动总线
- SendByte(sla); //发送器件地址
- if(ack==0)return(0);
- SendByte(c); //发送数据
- if(ack==0)return(0);
- Stop_I2c(); //结束总线
- return(1);
- }
- */
-
- /*----------------------------------------------------------------
- 向有子地址器件发送多字节数据函数
- 函数原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);
- 功能: 从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
- 地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
- 如果返回1表示操作成功,否则操作有误。
- 注意: 使用前必须已结束总线。
- ----------------------------------------------------------------*/
- /*bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
- {
- unsigned char i;
- for(i=0;i<no;i++)
- {
- Start_I2c(); //启动总线
- SendByte(sla); //发送器件地址
- if(ack==0)return(0);
- SendByte(suba); //发送器件子地址
- if(ack==0)return(0);
-
- SendByte(*s); //发送数据
- if(ack==0)return(0);
- Stop_I2c(); //结束总线
- DelayMs(1); //必须延时等待芯片内部自动处理数据完毕
- s++;
- suba++;
- }
- return(1);
- }
- */
- /*----------------------------------------------------------------
- 向无子地址器件读字节数据函数
- 函数原型: bit IRcvByte(unsigned char sla,ucahr *c);
- 功能: 从启动总线到发送地址,读数据,结束总线的全过程,从器件地
- 址sla,返回值在c.
- 如果返回1表示操作成功,否则操作有误。
- 注意: 使用前必须已结束总线。
- ----------------------------------------------------------------*/
- /*bit IRcvByte(unsigned char sla,unsigned char *c)
- {
- Start_I2c(); //启动总线
- SendByte(sla+1); //发送器件地址
- if(ack==0)return(0);
- *c=RcvByte(); //读取数据
- NoAck_I2c(); //发送非就答位
- Stop_I2c(); //结束总线
- return(1);
- }
-
- */
- /*----------------------------------------------------------------
- 向有子地址器件读取多字节数据函数
- 函数原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);
- 功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
- 地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
- 如果返回1表示操作成功,否则操作有误。
- 注意: 使用前必须已结束总线。
- ----------------------------------------------------------------*/
- /*bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
- {
- unsigned char i;
-
- Start_I2c(); //启动总线
- SendByte(sla); //发送器件地址
- if(ack==0)return(0);
- SendByte(suba); //发送器件子地址
- if(ack==0)return(0);
-
- Start_I2c();
- SendByte(sla+1);
- if(ack==0)return(0);
-
- for(i=0;i<no-1;i++)
- {
- *s=RcvByte(); //发送数据
- Ack_I2c(); //发送就答位
- s++;
- }
- *s=RcvByte();
- NoAck_I2c(); //发送非应位
- Stop_I2c(); //结束总线
- return(1);
- }
- */
复制代码
|