程序设计 给你的电路注入灵魂 - 基础电路 - 博趣

  无线电   专题策划 行业动态 测试测量 单片机 精彩制作 精品套件 基础入门 试阅与下载 往期目录 官方淘宝店 制汇节
当前位置:博趣 -> 无线电 -> 基础入门 -> 基础电路

TOP

程序设计 给你的电路注入灵魂
发表日期:2010-07-14 14:14:37 来源:《无线电》杂志 2009.01 作者:魏坤 【 】 浏览:7375次 评论:0


没有程序,那一堆堆电路起不到任何作用,完全是一堆废板子!就像一台没有操作系统的电脑一样,只能废电。程序设计是整个示波器制作中的难点,本文将详细讲解程序的设计。该示波器中的程序全部是用C语言编写的,开发环境为CodeVisionAVR C,源程序可到《无线电》网站(www.radio.com.cn )下载,下面就各个重要的子程序的设计一一叙述,其他程序见源程序。MCU2与MCU1的程序流程图分别见图1和图2。

 


同步触发的软实现


细心的朋友也许会发现这个示波器电路中缺少一部分电路,就是硬件触发电路。为了降低电路的复杂性,我没有做这个电路,而是用软件实现同步触发的。虽然这样做有个弊端,就是几乎无法实现单次触发,但是我基本不用这个功能。要用这个功能的朋友只需在程控放大器部分加上一个由高速比较器构成的迟滞比较器,然后将输出端接到一个外部中断的输入口即可。当然程序和电路就要作相应的变化,这里就不多讲了。软件触发的好处是触发条件更易调整,只需调整比较语句中的参数即可。保证可以用软件触发的条件是要有足够大的存储空间,显示一屏的数据为240个,但每次读进单片机的数据为500个,多余260个数据就是作为不满足触发条件的舍弃余量。为了以防万一,当从500个数据中已经读出超过260个数据但还没有符合触发条件的数据时,将跳出触发比较循环,重新从FIFO存储器中读出500个数据,因为FIFO存储器为4K容量,最多可以这样重复读取8次数据,所以软触发可以非常稳定地工作,在该示波器的MCU2中控制触发的语句见以下程序段:


程序的意思是只有当此时采样信号的数值是m且为上升沿时才可以触发,改变触发沿只需改变运算符,改变触发电压只需改变m的值即可,m的取值范围是0~255。
从采样数据中测信号峰峰值
本示波器能够测量输入信号电压的峰峰值,并显示在屏幕上。这个功能由峰峰值测量子程序完成,见下面的程序段。 
在程序开始时给a中赋值128,即基线电压值。因为一屏幕的显示数据为240个,所以用for()循环将if…else…判断语句执行240次,在a中存放最大值,在b中存放最小值。对每个数据进行比较,如果该数据比a大则将这个数据存入a,如果小于a,则将这个数据与b进行比较,比b大则抛弃,比b小则存入b。故当240个循环执行完后,a中存放的是这一屏幕数据中的最大值,b中存放的是这一屏幕显示数据中的最小值。在比较完后用a减去b,得到差值存入c中,则c中保存的值就是电压的峰峰值,调用电压计算显示子程序,根据当前的垂直灵敏度给c乘以不同的倍数,得到实际的峰峰值。当前垂直灵敏度的判断由一个switch()选择结构完成。biao寄存器中的数据是当前的垂直灵敏度,case 4:后面没有运算是因为程控放大器在此状态下的放大倍数为1,即没有放大也没有衰减。   
在计算完峰峰值后,设置LCD显示器,使其工作在文本模式(因为只有在文本模式下对字库的调用才有效),然后设置屏幕上显示电压峰峰值的坐标(对该LCD模块的控制是先送命令,后送参数。例如设置X坐标“SdCmd(0x60);SdCmd(30);”中,第一个SdCmd()送的0x60是设置X坐标的命令,第二个SdCmd()送的30是X轴的坐标,其他设置相同。具体见光盘中LCD显示屏的资料。),在设置完LCD后约定显示格式,小数点后保留2位有效数字,显示单位为Vpp,显示完毕后需重新设置LCD工作状态,使其工作在图形模式用于波形显示。

 


将采样数据转换成显示数据
LCD显示屏为320×240点阵的图形显示模块,内置RA8803 控制器。模块不仅可以显示单一的文本、图形,而且可以实现双图层的(“或”、“异或”、“同或”、“与”四种逻辑关系)合成显示。在本示波器中方格线与波形是在不同的层上显示,显示关系为“或”,画方格线的程序见原程序,比较简单就不多说了,这里着重解释一下如何将采样数据转换成显示数据。 
显示屏的地址结构见图3,由图可知对显示数据的操作最小单位为字节,因为ATmega32的内存为2K字节,显示波形的区域为240×240,显示一屏波形所需处理的数据为7.2K,故ATmega32不可能同时处理一屏波形的全部数据,所以将一屏波形按字节分为30列,每次处理一列,处理完后直接显示,然后处理下一列。将AD转换所得的数据作为给LCD显示器写数据的列地址,因为一列数据位240字节,所以定义一个容量为240字节的数组lcd_buffer[240],lcd_buffer[ ]在初始时数据全为00H,因为每次对数据的操作至少是一个字节,而每次处理的数据是所显示的一个点,所以对每列数据处理8次,定义一个变量m,在一列数据处理之前将其赋值为m=10000000B,处理该列第1个点时让该点垂直地址所对应的数组中的数据(00H)与m相或,并将结果存入数组,再将变量m右移一位,即m=01000000B。让第2点垂直地址所对应的数组中的数据与m相或,并将结果存入数组,再将变量m右移一位,即m=00100000B ……这样直到一列数据中的8个点全处理完,重新给m赋值为m=10000000B,然后送显示。为了有较好显示效果,将显示相邻的点用线连接起来,在处理第一个点时预读出第二个点的垂直坐标,与第一个点的垂直坐标进行比较,如果比第一个点的垂直坐标小则从第一个点向第二个点拉线,如果比第一个点的垂直坐标大则从第二个点向第一个点拉线。具体程序如下:    

 

   

 


用MCU1频率测量

用ATmega8测量频率使用了其中的两个计数器/定时器。设置TCCR1B=6使16位计数器/定时器T/C1工作在计数器方式,对外部T1(PD5)引脚输入的脉冲信号进行计数(下降沿触发)。

 

设置TCCR2=15使T/C2工作在CTC模式,内部时钟1024分频(16M/1024=15.625kHz),设置OCR2=124,使中断时间为(124+1)/15.625=8ms,在低水平扫速时每隔8ms中断一次,在高水平扫速时通过重新设置TCCR2=14,则每隔2ms中断一次,在这里以低水平扫速时为例,每次T/C2的中断中都首先记录下T/C1寄存器TCNT1当前的计数值,因此前后两次寄存器TCNT1的差值(time1_new-time1_old)或(65536-time1_old+time1_new)就是8ms时间内T1引脚输入的脉冲个数,为了提高测量精度程序对125个8ms内的脉冲个数进行累计,将累计值存入变量freq中,即可知限定时间为1s内有多少个脉冲,这样就将T1脚上的脉冲频率测量出来了,而T1脚上的频率是经过4分频后的,所以真正的频率是将测量的频率的4倍。具体程序如下: 

 

 

 


将两个单片机联系起来
将两个单片机联系起来就是实现两个单片机之间的通信,在这里实际就是让MCU1控制MCU2,为了完成这一功能使用SPI通信。        
首先介绍一下SPI的通信协议:SPI(串行外设接口)总线系统是一种同步串行外设接口,允许MCU与各种外围设备以串行方式进行通信、数据交换,广泛应用于各种工业控制领域。基于此标准,SPI系统可以直接与各个厂家生产的多种标准外围器件直接接口。SPI接口通常包含有4根线:串行时钟(SCK)、主机输入/从机输出数据线(MISO)、主机输出/从机输入数据线(MOSI)和低电平有效的从机选择线SS。在从机选择线SS使能的前提下,主机的SCK脉冲将在数据线上传输主/从机的串行数据。主/从机的典型连接图如图4所示。        
串行外设接口SPI允许AVR单片机和外设之间进行高速的同步数据传输。AVR单片机SPI的特点如下:全双工,3线同步数据传输,主/从机操作,LSB首先发送或MSB首先发送,7种可编程的比特率,传送中断结束,写碰撞标志检测,可以从闲置模式唤醒。SPI主机-从机的互连如图5所示,系统包括两个移位寄存器和一个主时钟发生器。通过将需要的从机的SS引脚拉低,主机启动一次通信过程。主机和从机将需要的数据放到相应的移位寄存器,主机在SCK引脚上产生时钟脉冲以交换数据。主机的数据从MOSI移出,从从机MISO移入。从机的数据从MISO移出,从从机MOSI移入。主机通过将从机的SS拉高实现与从机的同步。  
下面将介绍SPI的几个特殊寄存器:
(1)    SPI的控制寄存器—SPCR(见图6) 

 


 SPIE为SPI中断使能,置位后,只要SPSR寄存器的SPIF和SREG寄存器的全局中断使能位置位,就会引发SPI中断。SPE置位将使能SPI,DORD置位时数据的LSB首先发送;否则数据的MSB首先发送。MSTR置位时选择主机模式,否则为从机。CPOL置位表示空闲时SCK为高电平;否则空闲时SCK为低电平。CPHA决定数据是在SCK的起始沿采样还是在SCK的结束沿采样。通过对SPR1、SPR0进行设计,确定主机的SCK速率。 
(2)SPI的状态寄存器—SPSR(见图7)SPIF为中断标志位,串行发送结束后,SPIF置位。若此时寄存器 SPCR的SPIE和全局中断使能位置位,SPI中断即产生。进入中断例程后SPIF将自动清零。在发送当中对SPI数据寄存器SPDR写数据将置位WCOL,SPI2X置位后SPI的速度加倍。    

(3)SPI的数据寄存器—SPDR(见图8)SPDR数据寄存器为读/写寄存器,用来在寄存器文件SPI移位寄存器之间传输数据。写寄存器将启动数据传输,读寄存器将读取寄存器的接收缓冲器。SPI系统的发送方向只有一个缓冲器,而在接收方向有两个缓冲器。也就是说,在发送数据时一定要等到移位过程全部结束后才能对SPI数据寄存器执行写操作。而在接收数据时,需要在下一个字符移位过程结束之前通过访问SPI数据寄存器读取当前接收到的字符。否则第一个字节将丢失。   
本示波器中只用MCU1控制MCU2,所以MCU1只用于发送控制数据,而MCU2只用于接收控制数据,所以将MCU1配制成SPI主机,将MCU2配制成SPI从机即可。在实际的程序设计中由于MCU1启动SPI通信是在中断服务程序中完成,所以在执行完后相应寄存器会被清零,导致数据错误,所以MCU1并没有使用其中的SPI控制器,而是使用一个子程序模拟SPI通信,解决了控制寄存器被清零的问题。MCU2则使用了本身的SPI控制器进行数据接收。具体程序见以下程序段 :         MCU1模拟SPI主机程序段spi_out()为SPI发送子程序,带有参数j,即j为要发送的数据,发送数据时先拉低ss,让从机开始接收数据,然后用for()循环将数据按由左至右的顺序(即高位先发送)发送给从机,具体方法是将j与0b10000000相与,屏蔽低7位,是1则将dat拉高,否则置低,然后拉高clk,延时1us再置低clk,模拟时钟信号,再将j左移一位,再与0b10000000相与,然后判断发送……直到8位数据发送完毕,拉高ss告诉从机数据发送完毕进行数据存储。发送数据时约定数据格式,即两个单片机之间的通信协议:每次发送9个字节,前4个字节是测得的频率数据,且高位在前;第5个字节为垂置灵敏度数据;第6个字节为触发控制数据;第7个字节为同步控制数据;第8个字节为水平扫速数据;第9个字节为功能复用键的当前功能标志。从机再接收到数据后按照这样的顺序对数据进行处理,实现相应的功能。spi_out()这个子程序还可以用于其他需要SPI控制的芯片,只需在调用前对I/O口进行定义即可。   

 

 
(2)MCU2从机SPI程序段
init_spi()函数是将MCU2配制成SPI从机,每接收一个字节的数据中断一次,中断服务程序中将接收到的数据存入数组,并将数组地址加1,然后判断9个字节是否接收完毕,若没接收完则继续等待接收,接收完后则将数据按约定格式处理显示。大家可以根据自己的需求改变这些格式为其增加新的功能。

 > 相关内容:

 
Tags:程序 电路 责任编辑:yanhuo
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇德生S-2000收音机电路简析(二) 下一篇硬件电路简述   电路才是“..

赞助商链接

最新文章

热门文章

推荐文章