
单片机课程设计报告
系 部: 电子通信工程系
专 业: 电子信息工程
班 级: 电信101
学生姓名: 刘军
学 号: 100407106
2013/1/16
课程设计报告
前言:
本文以8051f410单片机为核心设计了一个低频函数信号发生器。信号发生器采用数字波形合成技术,通过硬件电路和软件程序相结合,可输出自定义波形,如正弦波、方波、锯齿、三角波、及其他任意波形,波形的频率和幅度在一定范围内可任意改变。波形和频率的改变通过软件控制,幅度的改变通过硬件实现。介绍了波形的生成原理、硬件电路和软件部分的设计原理。本系统可以产生最高频率99999HZ的波形。该信号发生器具有体积小、价格低、性能稳定、功能齐全的优点。
设计报告:
一、工作原理
数字信号可以通过数/模转换器转换成模拟信号,因此可通过产生数字信号再转换成模拟信号的方法来获得所需要的波形。8051f410单片机本身就是一个完整的微型计算机,具有组成微型计算机的各部分部件:处理器CPU、随机存取存储器RAM、只读存储器ROM、I/O接口电路、定时器/计数器以及串行通讯接口等,只要将8051f410再配置键盘及、及波形输出、放大电路等部分,即可构成所需的波形发生器。经过考虑,我们确定方案如下:利用F410单片机采用程序设计方法产生锯齿波、三角波、正弦波、方波四种波形,再通过D/A转换器将数字信号转换成模拟信号,滤波放大,最终由示波器显示出来,通过键盘来控制四种波形的类型选择、频率变化,最终输出显示其各自的类型以及数值。
1.1、设计要求
1)、利用单片机采用软件设计方法产生四种波形
2)、四种波形可通过键盘选择
3)、波形频率可调
4)、需显示波形的种类及其频率
二、主程序思路
主程序先是进行一些初始化的工作,然后根据波形标志代码的值,使其形成多个数组,每个数组都是一个波形代码。这样写的好处是输出的波形频率也可以有定时常数决定,找到定时常数和输出频率的关系。在按键设置波形转换状态的循环中,波形的转换状态在按键上可以一一看出,把四种波形设置成0、1、2、3、在数码管的最高位设置成循环显示,然后把每个波形的代码值通过单片机自带的AD转换赋给输出的数据口,确定每个数组然后确定数组的列是否为数组中最后行的一个元素,若是则运行下一行的元素(另一个波形),并通过端口输出P0.0。同时还要有按键控制频率,因为找到输出频率和定时常数的关系,所以频率的调节,可以有一个按键控制频率的个位、十位、百位、千位,再通过另一按键分别可以在频率的个位、十位、百位、千位进行加一功能,则实现了频率的要求调节,然后再把频率通过数码管的低四位一一显示出来,即构成四位的频率。
主程序流程图
三、软件流程程序:
本程序中两个外部中断分别起到了控制波形和频率的作用。在程序中还加入了消抖部分。
软件流程图
4、电路板图:
6、程序六
7、#include sbit CH452_SCL = P1^3; sbit CH452_SDA = P1^4; sbit CH452_KEY = P1^5; unsigned char second0,second1,minute0,minute1,f,j; //四个参数 unsigned char tc,sta=0x08,stb=0x01; //软件延时单元,状态标志 code unsigned char ds=0x14; //软件延时系数__20 bit flag1=0; unsigned char k,dispbuff[] = {0,0,0,0,0,0,0,0}; //显示缓冲,初始显示全0 unsigned int CMD,DAT,DAT1; unsigned char buffer[]={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,}; code unsigned char font[32] = { 0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0, //01234567 0xFE,0xF6,0xEE,0x3E,0x9C,0x7A,0x9E,0x8E, //ABCDEF 0xFD,0x61,0xDB,0xF3,0x67,0xB7,0xBF,0xE1, //0.1.2.3.4.5.6.7. 0xFF,0xF7,0x00,0x62,0x02,0x12,0x7C,0x1C};//8.9.灭 + — = U L code unsigned char key[16] = { 0xC6,0xB6,0x86,0xD6,0x96,0xA6,0xF6,0xE6, 0xC4,0xB4,0x84,0xD4,0x94,0xA4,0xF4,0xE4 };//键盘位置码 code unsigned int table1[4][32]={ 4095,4095,4095,4095,4095,4095,4095,4095,4095,4095,4095,4095,4095,4095,4095,4095, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256,512,768,1024,1280,1536,1792,2048,2304,2560,2816,3072,3328,3584,3840,4095,3840,3584,3328,3072,2816,2560,2304,2048,1792,1536,1280,1024,768,512,256, 2048,2447,2831,3185,3496,3750,3940,4056,4095,4057,3941,3752,3498,3188,2834,2451,2051,1652,1268,913, 603, 348, 158, 40, 0, 38, 154, 342, 596,905,1259,12, 0, 132, 2,396, 528,660, 792,924, 1056,1188,1320,1452,1584,1716,1848,1980,2112,2244,2376,2508,20,2772,2904,3036,3168,3300,3432,35,3696,3828,3960,4092}; //二维数组(方波,锯齿波,正弦波 ,三角波) /* mS延时 */ void delayms(unsigned int i) { unsigned int j; do{ for(j=0;j!=1000;j++) {;} }while(--i); } ///////////////////////////////////////////////////////////////////////////////////// /* uS延时 */ void delayus(void) { unsigned int k; for (k=0;k<8;k++) {;} } unsigned char rdch452(void) { unsigned char j,key; CH452_SDA = 0; delayus(); CH452_SCL = 0; delayus(); CH452_SCL = 1; delayus(); CH452_SCL = 0; key = 0x9F; for (j=0;j<8;j++) { if (key>=0x80 ) CH452_SDA = 1; else CH452_SDA = 0; CH452_SCL = 1; delayus(); CH452_SCL = 0; key = key << 1 ; }; delayus(); key = 0; for (j=0;j<8;j++) { CH452_SCL = 1; if (CH452_SDA == 1) key ++; key = key << 1; CH452_SCL = 0; delayus(); } CH452_SDA = 1; delayus(); CH452_SCL = 1; return key; } ///////////////////////////////////////////////////////////////////////////////////////////////////// /* 命令、数据送CH452 */ void toch452(unsigned int cmda) { unsigned char j; CH452_SDA = 0; delayus(); CH452_SCL = 0; delayus(); CH452_SCL = 1; delayus(); CH452_SCL = 0; for (j=0;j<16;j++) { if (cmda>=0x8000 ) CH452_SDA = 1; else CH452_SDA = 0; CH452_SCL = 1; delayus(); CH452_SCL = 0; cmda = cmda << 1 ; }; CH452_SDA = 1; delayus(); CH452_SCL = 1; } ///////////////////////////////////////////////////////////////////////////////////// /* 读键盘 */ //////////////////////////////////////////////////////////////////////////////////// void display(void) { unsigned char i; DAT1 = 0xA100; //8个数码管逐一送显示 for (i=0;i<8;i++) { DAT = DAT1 + font[dispbuff [i]]; toch452(DAT); DAT1 = DAT1 + 0x0400; } } void sx (void) //送显示函数 { dispbuff[0]=second0; //频率个位 dispbuff[1]=second1; //频率十位 dispbuff[2]=minute0; //频率 百位 //"-" dispbuff[3]=minute1; //频率千位 dispbuff[4]=29; //等号 dispbuff[5]=15; //"f" dispbuff[6]=26; //不显示 dispbuff[7]=j%10; //转换波形状态 } unsigned int key1(void) { unsigned char i,keycode,keyn; if (CH452_KEY == 0 ) //查询键盘 { keycode = rdch452(); //将键值赋给变量keycode keyn = 0; for (i=0;i<16;i++) //键译码 { if (key[i] == keycode) keyn = i ; } switch (keyn) { case 0://转换波形,有二维数组4行,32列, { for(i=0;i<32;i++) { buffer[i]=table1[j][i];//把数组中的单行数组,一次送到数组buffer中 } j=j+1;//行 if(j==4) j=0; }break; case 1: //转换状态 { sta=sta+sta; if(sta==0x10) sta=0x01; } break; case 2: //校频率位 { switch (sta) { case 0x01: //校频率个位 { second0++; if(second0==10) { //second1++; second0=1; } } break; case 0x02: //校十位 { second1++; if(second1==10) { second1=0; } } break; case 0x04: //校百位 { minute0++; if(minute0==10) { minute0=0; } } break; case 0x08: //千位 { minute1++; if(minute1==10) { minute1=0; } } } }; f=second0+second1*10+minute0*100+minute1*1000; } sx(); //送显 display(); //显示 } return(f); } void Init_Device(void) { PCA0MD &= ~0x40; //PCA_Init()禁止看门狗 PCA0MD = 0x00; IDA0CN = 0xF5; //DAC_Init() P1MDOUT = 0x00; P0MDIN = 0xFE; //Port_IO_Init() P0SKIP = 0x01; IDA0CN = 0xF2;//使能IDA0转换器 REF0CN = 0x08;//选择电源电压为IDA0的参考电压 P0MDIN = 0xFE;//使能交叉开关 } void main(void) { unsigned char i; Init_Device(); XBR1 = 0x40; PCA0MD = 0x00; OSCICN = 0x86;//选择系统时钟位24.5MHZ TMOD=0x10; //定时器1初始化 TH1=65536-1000000/(384*f); //输出频率和定时常数 TL1=65536-1000000%(384*f); EA=1; ET0=1; //开放定时器1中断 tc=ds; //软件延时初值 TR0=1; delayms(100); CMD = 0x9103; //设置CH452系统参数 1001 0001 0000 0011--> 0100 0000 0011 ---> 403 (低电平按键中断,1HZ闪烁,共阴管,开键盘,开显示) // ===> 413 (低电平按键中断,2HZ闪烁,共阴管,开键盘,开显示) toch452(CMD); CMD = 0x9500; //设置CH452显示参数 1001 0101 0100 0000--> 0101 0100 0000 ---> 540 (不译码,四位数码管扫描) // ===> 500 (不译码,8位数码管扫描) toch452(CMD); while(1) { key1(); //键处理 if(flag1==1) //有标志位 { flag1=0; IDA0H=buffer[i]; //输出波形 if(i<32)i++; else i=0; } sx(); //送显 display(); } } void timer0(void) interrupt 1 //定时器1中断服务函数 { flag1=1; TH1=65536-1000000/(384*f); TL1=65536-1000000%(384*f); } 七、心得体会 通过这次毕业设计,使我深刻地认识到学好专业知识的重要性,也理解了理论联系实际的含义,并且检验了大学三年的学习成果,进一步加深了我对专业知识的了解和认识以及动手的能力。虽然在这次设计中对于所学知识的运用和衔接还不够熟练,作品完成的还不是很出色。但是我将在以后的工作和学习中继续努力、不断完善。这个设计是对我们过去所学知识的系统提高和扩充的过程,为今后的发展打下了良好的基础。
