单片机产生正弦波
- 格式:doc
- 大小:533.50 KB
- 文档页数:8
单片机dac正弦波
要实现单片机上的DAC正弦波输出,可以按照以下步骤进行:
1. 首先,确定要输出正弦波的频率和幅值。
根据这些参数,计算出所需的波形数据点数。
2. 在单片机上配置一个定时器,用来产生固定的时钟信号。
这个时钟信号的频率应根据所需的正弦波频率来确定。
3. 在单片机的定时器中断服务程序中,利用查表法生成正弦波的波形数据。
可以预先计算好一段正弦波周期内的数据,并存储在一个数组中。
4. 在定时器中断服务程序中,通过DAC输出器件将波形数据
点输出到外部设备。
5. 在主函数中,启动定时器,并设置中断使能。
通过配置
DAC输出器件和外部电路连接,将DAC输出信号接到外部设
备上(如示波器)进行观测。
通过以上步骤,可以在单片机上实现DAC正弦波的输出。
需
要注意的是,具体的实现方式可能因单片机型号和编程语言不同而有所差异,因此还需根据实际情况进行适当的调整。
用单片机产生正弦波程序Document serial number【UU89WT-UU98YT-UU8CB-UUUT-UUT108】用单片机产生正弦波程序要用到数模转换DAC0832MOV DPTR,#SINTAB ;正弦表写入内部RAM6DH-7FH MOV R0,#6DHLOOP: CLR AMOVC A,@A+DPTRMOV @R0,AINC DPTRINC R0CJNE R0,#80H,LOOPMOV DPTR,#7FFFH ;设置D/A转换器的端口地址MOV R0,#6DH ;设置正弦表指针LOOP1: MOV A,@R0 ;查表MOVX @DPTR,A ;D/A转换ACALL DELAY ;延时,等待转换结束DEC R0 ;正弦表位移量增量CJNE R0, #6DH,LOOP1 ;第一象限输出完LOOP2: MOV A,@R0 ;查表MOVX @DPTR,A ;D/A转换acall DELAY ;延时,等待转换结束DEC R0 ;正弦表位移量减量CJNE R0, #6DH,LOOP2 ;第二象限输出完LOOP3: MOV A,@R0 ;查表CPL A ;表值取反MOVX @DPTR,A ;D/A转换ACALL DELAY ;延时,等待转换结束INC R0 ;正弦表位移量增量CJNE R0,#7FH,LOOP3 ;第三象限输出完LOOP4:MOV A,@R0 ;查表CPL A ;表值取反MOVX @DPTR,A ;D/A转换ACALL DELAY ;延时,等待转换结束DEC R0 ;正弦表位移量减量CJNE R0,#6DH,LOOP4 ;第四象限输出完 SJMP LOOP1DELAY:MOV R7,#200 ; 延时50msDEL1:MOV R6,#123NOPDEL2:JNZ R6,DEL2DJNZ R7,DEL1RETSINTAB:DB 80H,83H,86H,89H,8DH,90H,93H,96HDB 99H,9CH,9FH,0A2H,0A5H,0A8H,0ABH,0AEHDB 0B1H,0B4H,0B7H,0BAH,0BCH,0BFH,0C2H,0C5H DB 0C7H,0CAH,0CCH,0CFH,0D1H, 0D4H,0D6H,0D8H DB 0DAH,0DDH,0DFH,0E1H,0E3H, 0E5H,0E7H,0E9H DB 0EAH,0ECH,0EEH,0EFH,0F1H, 0F2H,0F4H,0F5H DB 0F6H,0F7H,0F8H,0F9H,0FAH, 0FBH,0FCH,0FDH DB 0FDH,0FEH,0FFH,0FFH,0FFH, 0FFH,0FFH,0FFH DB 0FFH,0FFH,0FFH,0FFH,0FFH, 0FFH,0FEH,0FDH DB 0FDH,0FCH,0FBH,0FAH,0F9H, 0F8H,0F7H,0F6H DB 0F5H,0F4H,0F2H,0F1H,0EFH, 0EEH,0ECH,0EAH DB 0E9H,0E7H,0E5H,0E3H,0E1H, 0DEH,0DDH,0DAH DB 0D8H,0D6H,0D4H,0D1H,0CFH, 0CCH,0CAH,0C7H DB 0C5H,0C2H,0BFH,0BCH,0BAH, 0B7H,0B4H,0B1H DB 0AEH,0ABH,0A8H,0A5H,0A2H, 9FH, 9CH, 99H DB 96H, 93H, 90H, 8DH, 89H, 86H, 83H, 80H DB 80H, 7CH, 79H, 78H, 72H, 6FH, 6CH, 69H DB 66H, 63H, 60H, 5DH, 5AH, 57H, 55H, 51H DB 4EH, 4CH, 48H, 45H, 43H, 40H, 3DH, 3AH DB 38H, 35H, 33H, 30H, 2EH, 2BH, 29H, 27H DB 25H, 22H, 20H, 1EH, 1CH, 1AH, 18H, 16H DB 15H, 13H, 11H, 10H, 0EH, 0DH, 0BH, 0AHDB 09H, 08H, 07H, 06H, 05H, 04H, 03H, 02H DB 02H, 01H, 00H, 00H, 00H, 00H, 00H, 00H DB 00H, 00H, 00H, 00H, 00H, 00H, 01H, 02H DB 02H, 03H, 04H, 05H, 06H, 07H, 08H, 09H DB 0AH, 0BH, 0DH, 0EH, 10H, 11H, 13H, 15H DB 16H, 18H, 1AH, 1CH, 1EH, 20H, 22H, 25H DB 27H, 29H, 2BH, 2EH, 30H, 33H, 35H, 38H DB 3AH, 3DH, 40H, 43H, 45H, 48H, 4CH, 4EH DB 51H, 55H, 57H, 5AH, 5DH, 60H, 63H, 66H DB 69H, 6CH, 6FH, 72H, 76H, 79H, 7CH, 80H END。
电子科技大学吴鉴鹰#include <c8051f020.h> // SFR declarations#include <intrins.h>#include <stdio.h>#include<math.h>#define uchar unsigned char#define uint unsigned intuchar i,j,colour=1,T=0;#define Lcd_Bus P5/*char code seg[360] = {0x80,0x82,0x84,0x86,0x88,0x8b,0x8d,0x8f,0x91,0x94, 0x96,0x98,0x9a,0x9c,0x9e,0xa1,0xa3,0xa5,0xa7,0xa9, 0xab,0xad,0xaf,0xb1,0xb4,0xb6,0xb8,0xba,0xbc,0xbe, 0xbf,0xc1,0xc3,0xc5,0xc7,0xc9,0xcb,0xcc,0xce,0xd0, 0xd2,0xd3,0xd5,0xd7,0xd8,0xda,0xdc,0xdd,0xdf,0xe0, 0xe2,0xe3,0xe4,0xe6,0xe7,0xe8,0xea,0xeb,0xec,0xed, 0xee,0xef,0xf0,0xf2,0xf3,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xf9,0xfa,0xfb,0xfb,0xfc,0xfc,0xfd,0xfd,0xfe,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfe,0xfd,0xfd,0xfc,0xfc,0xfb,0xfb,0xfa,0xf9,0xf9,/*0xf8,0xf7,0xf6,0xf5,0xf4,0xf4,0xf3,0xf2,0xf1,0xf0, 0xee,0xed,0xec,0xeb,0xea,0xe8,0xe7,0xe6,0xe4,0xe3, 0xe2,0xe0,0xdf,0xdd,0xdc,0xda,0xd9,0xd7,0xd5,0xd4, 0xd2,0xd0,0xce,0xcd,0xcb,0xc9,0xc7,0xc5,0xc3,0xc2, 0xc0,0xbe,0xbc,0xba,0xb8,0xb6,0xb4,0xb2,0xb0,0xae, 0xab,0xa9,0xa7,0xa5,0xa3,0xa1,0x9f,0x9c,0x9a,0x98, 0x96,0x94,0x92,0x8f,0x8d,0x8b,0x89,0x86,0x84,0x82, 0x80,0x7d,0x7b,0x79,0x77,0x75,0x72,0x70,0x6e,0x6c, 0x69,0x67,0x65,0x63,0x61,0x5f,0x5c,0x5a,0x58,0x56, 0x54,0x52,0x50,0x4e,0x4c,0x4a,0x48,0x46,0x44,0x42, 0x40,0x3e,0x3c,0x3a,0x38,0x36,0x34,0x33,0x31,0x2f, 0x2d,0x2c,0x2a,0x28,0x27,0x25,0x24,0x22,0x21,0x1f, 0x1e,0x1c,0x1b,0x19,0x18,0x17,0x16,0x14,0x13,0x12, 0x11,0x10,0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8,0x7, 0x7, 0x6, 0x5, 0x5, 0x4, 0x3, 0x3, 0x2, 0x2,0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1,0x1, 0x2, 0x2, 0x3, 0x3, 0x4, 0x4, 0x5, 0x6, 0x6,0x7, 0x8, 0x9, 0xa, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,0x10,0x12,0x13,0x14,0x15,0x16,0x18,0x19,0x1a,0x1c, 0x1d,0x1f,0x20,0x22,0x23,0x25,0x26,0x28,0x2a,0x2b, 0x2d,0x2f,0x30,0x32,0x34,0x36,0x38,0x39,0x3b,0x3d, 0x3f,0x41,0x43,0x45,0x47,0x49,0x4b,0x4d,0x4f,0x51,0x53,0x55,0x58,0x5a,0x5c,0x5e,0x60,0x62,0x65,0x67,0x69,0x6b,0x6d,0x70,0x72,0x74,0x76,0x78,0x7b,0x7d};*/#define SYSCLK 22118400 // SYSCLK frequency in Hz #define INT_DEC 256 // integrate and decimate ratio #define _Nop() _nop_()//#define FIRST_ADDR 0//-----------------------------------------------------------------------------// 16-bit SFR Definitions for 'F02x//-----------------------------------------------------------------------------sfr16 DP = 0x82; // data pointersfr16 TMR3RL = 0x92; // Timer3 reload valuesfr16 TMR3 = 0x94; // Timer3 countersfr16 ADC0 = 0xbe; // ADC0 datasfr16 ADC0GT = 0xc4; // ADC0 greater than window sfr16 ADC0LT = 0xc6; // ADC0 less than windowsfr16 RCAP2 = 0xca; // Timer2 capture/reloadsfr16 T2 = 0xcc; // Timer2sfr16 RCAP4 = 0xe4; // Timer4 capture/reloadsfr16 T4 = 0xf4; // Timer4sfr16 DAC0 = 0xd2; // DAC0 datasfr16 DAC1 = 0xd5; // DAC1 data//-----------------------------------------------------------------------------// 液晶接口定义//-----------------------------------------------------------------------------//#define LEDCTL0Low P4&=~0x01;//#define LEDCTL0High P4|=0x01;#define LCDELow P4&=~0x02;#define LCDEHigh P4|=0x02;#define LCDRWLow P4&=~0x04;#define LCDRWHigh P4|=0x04;#define LCDRSLow P4&=~0x08;#define LCDRSHigh P4|=0x08;#define LCDPSBLow P4&=~0x10;#define LCDPSBHigh P4|=0x10;//==============================//uchar num;uint delay_time;/*-----------------------------------------------------*/void SYSCLK_Init (void);void PORT_Init (void);//----------------------------------------------------------------------------- ////-----------------------------------------------------------------------------void delay(unsigned int t){ unsigned int k,j;for(k=0;k<t;k++)for(j=0;j<10;j++) ;}/*void delay(unsigned int t){unsigned int i,j ;for(i=0;i<t;i++)for(j=0;j<10;j++);}*///----------------------------------------------------------------------------- ////-----------------------------------------------------------------------------void delay18(uint k){ while(k){ k--; }}//----------------------------------------------------------------------------- // 液晶显示写命令//----------------------------------------------------------------------------- void write_com(unsigned char cmdcode){LCDRSLow;LCDRWLow;LCDEHigh;Lcd_Bus=cmdcode;delay(50);delay(60); //在数据写入的时候加入适当的延时LCDELow;delay(50);delay(60);}//-----------------------------------------------------------------------------// 液晶显示写数据//-----------------------------------------------------------------------------void write_data(unsigned char Dispdata){LCDRSHigh;LCDRWLow;LCDEHigh;Lcd_Bus=Dispdata;delay(50);delay(60); // 在数据写入的时候加入适当的延时LCDELow;delay(50);delay(60);}void chk_busy(){LCDRSLow;LCDRWHigh;LCDEHigh;Lcd_Bus=0xff ;while((Lcd_Bus&0x80)==0x80);LCDELow;}/*------------------写命令到LCD------------------------------*//*void write_com(unsigned char cmdcode){chk_busy();LCDRSLow ;LCDRWLow ;LCDEHigh ;Lcd_Bus=cmdcode ;delay(5);//------------------在数据写入的时候加入适当的延时LCDELow ;delay(5);}*//*-------------------写数据到LCD----------------------------*//*void write_data(unsigned char Dispdata){chk_busy();LCDRSHigh ;LCDRWLow ;LCDEHigh ;Lcd_Bus=Dispdata ;delay(5);//------------------在数据写入的时候加入适当的延时LCDELow ;delay(5);}*///-----------------------------------------------------------------------------// 液晶显示,复位初始//-----------------------------------------------------------------------------void lcdreset(){delay(200);delay(250);write_com(0x30);delay(100);delay(250); //选择基本指令集write_com(0x30); //选择8bit数据流delay(50);delay(250);write_com(0x0c); //开显示(无游标、不反白)delay(50);delay(250);write_com(0x01); //清除显示,并且设定地址指针为00Hdelay(50);delay(250);write_com(0x06); //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位}//-----------------------------------------------------------------------------// 液晶显示//-----------------------------------------------------------------------------/*void display(unsigned char code *s){while(*s>0){ write_data(*s);s++;delay(50);delay(100);}}*/void hzkdis(unsigned char code*s){while(*s>0){write_data(*s);s++;delay(50);}}/*------------------首屏显示--------------------------*///-----------------------------------------------------------------------------// 液晶显示内容//-----------------------------------------------------------------------------/*void zero_screen(){write_com(0x01);delay18(10000);//write_com(0x80);//display("电子科技大学");write_com(0x90);//display("省单片机精品课程");display("C8051F020 开发板");write_com(0x88);//display("C8051F020 开发板");display(" QQ:1811728618 ");//write_com(0x98);//display(" QQ:1811728618 ");}*//*------------------显示字符串--------------------------*/void ceshi(){write_com(0x01);//清除显示,并且设定地址指针为00Hdelay(5);write_com(0x80);//第一行(如果是地址是:80H,即LCD的第一行的第一个位置显示)hzkdis("电子科技大学");write_com(0x90);//第二行(如果是地址是:90H,即LCD的第二行的第一个位置显示)hzkdis("通信与信息工程");write_com(0x88);//第三行(如果是地址是:88H,即LCD的第二行的第一个位置显示)hzkdis("电子信息工程");write_com(0x98);//第四行(如果是地址是:98H,即LCD的第二行的第一个位置显示)hzkdis("郑海波测试程序");}/*------------------初始化LCD屏--------------------------*//*void lcdreset(){LCDPSBHigh;delay(2000);write_com(0x30);delay(10);//选择基本指令集write_com(0x30);//选择8bit数据流delay(5);write_com(0x0c);//开显示(无游标、不反白)delay(10);write_com(0x01);//清除显示,并且设定地址指针为00Hdelay(500);write_com(0x06);//指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位delay(0);}*///-----------------------------------------------------------------------------// 通用I/O口及交叉开关初始化//-----------------------------------------------------------------------------void PORT_Init (void){XBR2 = 0x40; // 交叉开关使能P74OUT=0xff;}//-----------------------------------------------------------------------------// 系统时钟初始化//-----------------------------------------------------------------------------/*void SYSCLK_Init() 本来就不用的{OSCICN =0x87; //使用内部时钟16Mwhile((OSCICN & 0x10)==0);//内部时钟按设定频率运行}*/// 配置系统时钟使用外部晶振11.0592MHzvoid SYSCLK_Init (void){int i; // delay counterOSCXCN = 0x67; // start external oscillator with// 22.1184MHz crystal for (i=0; i < 256; i++) ; // XTLVLD blanking interval (>1ms)while (!(OSCXCN & 0x80)) ; // Wait for crystal osc. to settleOSCICN = 0x88; // select external oscillator as SYSCLK// source and enable missing clock// detector}//-----------------------------------------------------------------------------// 系统初始化//-----------------------------------------------------------------------------void init(){SYSCLK_Init();PORT_Init ();lcdreset();//zero_screen();}//-----------------------------------------------------------------------------// 主程序//-----------------------------------------------------------------------------/*void main(){WDTCN = 0xde;WDTCN = 0xad; //禁止看门狗定时器LCDPSBHigh;//LCDRSTHigh;init();zero_screen();P5=0xff;while(1){}} *///------------定义接口-------------///*sbit RS=P2^2 ;sbit RW=P2^3 ;sbit E=P2^4;sbit PSB= P2^5; //H=并口; L="串口";#define Lcd_Bus P0// P0 接LCM#define uchar unsigned char*///定义字符/汉字显示起始位置/*------------------检查忙位-----------------------------*//*------------------延时子程序-----------------------------*///------------------清整个GDRAM空间---------------------------- void clrgdram(){unsigned char x,y ;for(y=0;y<64;y++)for(x=0;x<16;x++){write_com(0x34);write_com(y+0x80);//行地址write_com(x+0x80);//列地址write_com(0x30);write_data(0x00);write_data(0x00);}}//------------------------------------------------------------void clrscreen(){write_com(0x01);delay(10);}unsigned char ReadByte(void){unsigned char byReturnValue ;chk_busy();Lcd_Bus=0xff ;LCDRSHigh ;LCDRWHigh ;LCDELow ;LCDEHigh;byReturnValue=Lcd_Bus ;LCDELow ;return byReturnValue ;}/*增加画点子程序函数功能:在坐标为(x,y)点画一个点参数意义X:12864屏幕的横坐标,范围是0到128(从左到右)Y:12864的纵坐标,范围是0到64(从上到下)Color:为1的时候表示为黑点*//*void DrawPoint(unsigned char X,unsigned char Y,unsigned char Color) {unsigned char Row,Tier,Tier_bit ;unsigned char ReadOldH,ReadOldL ;write_com(0x34);write_com(0x36);Tier=X>>4 ;Tier_bit=X&0x0f ;if(Y<32){Row=Y ;}{Row=Y-32 ;Tier+=8 ;}write_com(Row+0x80);write_com(Tier+0x80);ReadByte();ReadOldH=ReadByte();ReadOldL=ReadByte();write_com(Row+0x80);write_com(Tier+0x80);if(Tier_bit<8){switch(Color){case 0 :ReadOldH&=(~(0x01<<(7-Tier_bit))); break ;case 1 :ReadOldH|=((0x01<<(7-Tier_bit))); break ;case 2 :ReadOldH^=(0x01<<(7-Tier_bit)); break ;default :break ;}write_data(ReadOldH);write_data(ReadOldL);}else{switch(Color){case 0 :ReadOldL&=(~(0x01<<(15-Tier_bit))); break ;case 1 :ReadOldL|=((0x01<<(15-Tier_bit))); break ;case 2 :ReadOldL^=(0x01<<(15-Tier_bit)); break ;break ;}write_data(ReadOldH);write_data(ReadOldL);}write_com(0x30);}void main(void){//WDTCN = 0xde; // 关闭WDT//WDTCN = 0xad;SYSCLK_Init ();PORT_Init ();//LCDRWLow;//lcdreset();//zero_screen();//clrgdram();delay(2000);clrscreen();while(1){for(i=0;i<128;i++){/*unsigned char k;if(j>0x32) k=seg[i];else k=-seg[i];j=0x32-k;*//*j=sin(i);DrawPoint(i,j,colour);}//T+=4;delay(5000);}while(1);}*/void DrawPoint(unsigned char X,unsigned char Y,unsigned char Color) {unsigned char Row,Tier,Tier_bit ;unsigned char ReadOldH,ReadOldL ;write_com(0x34);write_com(0x36);Tier=X>>4 ;Tier_bit=X&0x0f ;{Row=Y ;}else{Row=Y-32 ;Tier+=8 ;}write_com(Row+0x80);write_com(Tier+0x80);ReadByte();ReadOldH=ReadByte();ReadOldL=ReadByte();write_com(Row+0x80);write_com(Tier+0x80);if(Tier_bit<8){switch(Color){case 0 :ReadOldH&=(~(0x01<<(7-Tier_bit))); break ;case 1 :ReadOldH|=(0x01<<(7-Tier_bit)); break ;case 2 :ReadOldH^=(0x01<<(7-Tier_bit)); break ;default :break ;}write_data(ReadOldH);write_data(ReadOldL);}else{switch(Color){case 0 :ReadOldL&=(~(0x01<<(15-Tier_bit))); break ;case 1 :ReadOldL|=(0x01<<(15-Tier_bit));case 2 :ReadOldL^=(0x01<<(15-Tier_bit)); break ;default :break ;}write_data(ReadOldH);write_data(ReadOldL);}write_com(0x30);}void main(void){uchar i,j,colour=1,T=0; LCDRWLow ;lcdreset();ceshi();clrgdram();delay(2000);clrscreen();while(1){for(i=0;i<128;i++){j=32-32*sin(2*i*3.14/(64+T)); DrawPoint(i,j,colour);}//T+=4;delay(5000);}while(1);}。
单片机产生正弦波一要求采用单片机map430g2553和运算放大器lmv358产生正弦波,周期1秒。
二思路可通过单片机产生PWM,调节参数寄存器的值,产生不同占空比的PWM信号。
若占空比的变化规律是正弦的,则滤波后可得到所需正弦波形。
其中,PWM(PulseWidthModulation)控制——脉冲宽度调制技术是通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形(含形状和幅值)。
图1为用PWM波代替正弦半波的例子。
(单片机输出图1b,滤波后得到图1a)三实践1PWM况只有1N=200个。
则2PWMPWM●SMCLK),12K;第二行中,设置为SMCLK=DCO(默认时钟源)。
TASSEL1将定时器时钟设置为SMCLK(若为TASSEL0则选择ACLK),且未分频。
模式选择MC_1为上升模式。
采用上述方法设置定时器时钟=SMCLK=DCO=1M赫兹。
●周期计数:上升模式表明定时器由0递增到一个上限值CCR0。
CCR0需设置。
因为周期T=1/200秒,而定时器时钟=SMCLK=DCO=1M赫兹,定时器周期t=1微秒,所以CCR0=T/t=5000,即5毫秒。
●高电平计数:定时器由0递增到一个上限值CCR0过程中,需设置脉宽CCR1。
并且K=CCR1/CCR0的数值每个周期(5毫秒)都变化一次,变化趋势满足正弦变化,200个5毫秒构成一个正弦变化周期。
为获得CCR1值,在matlab中输入:t=0:pi/100:2*pi;k=(sin(t)+1)/2;CCR1=round(4999*k);可获得201个CCR1值。
上式中,第一行设置了201个数,均匀分布在0-2pi之间,第一个和最后一个分别对应0弧度和2pi弧度;第二行计算201个正弦值,偏置为0.5,全幅度为1的正弦波幅度,如图2所示:图2偏置为0.5,全幅度为1的正弦波幅度第三行计算CCR1值,为k与CCR0(这里是5000)的乘积,并取了四舍五入(round函数)。
STC89C51单片机产生正弦波、方波、三角波LED显示频率源程序#include <stdio.h>#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit LATCH1=P2^6;//定义锁存使能端口段锁存sbit LATCH2=P2^7;// 位锁存unsigned char TempData[8]; //存储显示值的全局变量unsigned char code DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9unsigned char code DuanMa2[10]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};// 显示段码值0~9unsigned char code DuanMa1[3]={0x77,0x7c,0x39};unsigned char code WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码#define DataPort P0sbit keyA=P3^3;sbit keyB=P3^4;sbit keyC=P3^5;sbit wc=P1^0;sbit scl=P1^1;sbit sda=P1^2;sbit scl1=P1^3;sbit sda1=P1^4;sbit p5=P1^5;sbit p6=P1^6;sbit p7=P1^7;uint sign,ad;uchar temp[10], temp1[3];//定义显示区域临时存储数组uchar voltage; //定义浮点变量uchar l=0,m=100,n=0;uchar code sin[200] = {52,53,55,56,58,59,61,62,64,65,67,68,70,71,73,74,75,77,78,79,81,82,83,84,85,86,88,89,90,90,91,92,93,94,95,95,96,96,97,97,98,98,98,99,99,99,99,100,100,100,100,100,9 9,99,99,99,98,98,98,97,97,96,96,95,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,79,7 8,77,75,74,73,71,70,68,67,65,64,62,61,59,58,56,55,53,52,50,48,47,45,44,42,41,39,38,3 6,34,33,32,30,29,27,26,24,23,22,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,5,4,4,3,2,2,2,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,2,2,2,3,4,4,5,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,22,23,24,26,27,29,30,32,33,35,36,38,39,41,42,44,45,47,48,50};void DelayUs2x(unsigned char t){while(--t);}void DelayMs(unsigned char t){while(t--){//大致延时1mSDelayUs2x(245);DelayUs2x(245);}}void delay(){ ;; }void delay1(uchar x){uchar a,b;for(a=x;a>0;a--)for(b=110;b>0;b--);}void Delay2(unsigned int t){while(--t);}void Display(){uchar i;for(i=0;i<4;i++){DataPort=WeiMa[i]; //取位码LATCH2=1; //位锁存LATCH2=0;if(i==0) DataPort=DuanMa1[sign-1];else if(i==1) DataPort=DuanMa2[temp1[i]];else DataPort=DuanMa[temp1[i]]; //取显示数据,段码LATCH1=1; //段锁存LATCH1=0;Delay2(500); // 扫描间隙延时,时间太长会闪烁,太短会造成重影}}//pcf8591void init1(){sda1=1;delay();scl1=1;delay();}void start1() //开始信号{sda1=1;delay();scl1=1;delay();sda1=0;delay();}void stop1() //停止{sda1=0;delay();scl1=1;delay();sda1=1;delay();}void respons1() //应答{uchar i;scl1=1;delay();while((sda1==1)&&(i<250))i++;scl1=0;delay();}void write_byte1(uchar date) {uchar i,temp;temp=date;for(i=0;i<8;i++){temp=temp<<1;scl1=0;delay();sda1=CY;delay();scl1=1;delay();}scl1=0;delay();sda1=1;delay();}uchar read_byte1(){uchar i,k;scl1=0;delay();sda1=1;delay();for(i=0;i<8;i++){scl1=1;delay();k=(k<<1)|sda1;scl1=0;delay();}return k;}void write_add1(uchar date) //写入DA{start1();write_byte1(0x90);respons1();write_byte1(0x40);respons1();write_byte1(date);respons1();// delay1(100);stop1();}uchar read_add1( uchar address ) //读AD值{uchar date;start1();write_byte1(0x90);respons1();write_byte1(0x40|address);respons1();start1();write_byte1(0x91);respons1();date=read_byte1();stop1();return date;}//键盘void keyscan(){if(keyA==0){delay1(10);if(keyA==0)sign=1;while(!keyA);}if(keyB==0){delay1(10);if(keyB==0)sign=2;while(!keyB);}if(keyC==0){delay1(10);if(keyC==0)sign=3;while(!keyC);}}//eepromvoid start() //开始信号{sda=1;delay();scl=1;delay();sda=0;delay();}void stop() //停止{sda=0;delay();scl=1;delay();sda=1;delay();}void respons() //应答{uchar i;scl=1;delay();while((sda==1)&&(i<250))i++;scl=0;delay();}void init(){sda=1;delay();scl=1;delay();}void write_byte(uchar date){uchar i,temp;temp=date;for(i=0;i<8;i++){temp=temp<<1;scl=0;sda=CY;delay();scl=1;delay();}scl=0;delay();sda=1;delay();}uchar read_byte(){uchar i,k;scl=0;delay();sda=1;delay();for(i=0;i<8;i++){scl=1;delay();k=(k<<1)|sda;scl=0;delay();}return k;}void write_add(uchar date[],uchar address ) {uchar i,*pdate;pdate=date;for(i=0;i<2;i++){write_byte(0xae);respons();write_byte(address+i);respons();write_byte(*(pdate+i));respons();stop();}}void read_add(uchar date[] ,uchar address ) {uchar i,*pdate;pdate=date;for(i=0;i<2;i++){start();write_byte(0xae);respons();write_byte(address+i);respons();start();write_byte(0xaf);respons();*(pdate+i)=read_byte();stop();}}void sj(){if(l<100){write_add1(l);l++;}if(l>=100&m>0){write_add1(m);m--;}if(l>=100&m<=0){l=0;m=100;}p5=0;p6=1;p7=1;}void zx(){if(l<200){write_add1(sin[l]);l++;}if(l>=200)l=0;p6=0;p7=1;p5=1;}void fb(){if(l<100){write_add1(255);l++;}if(l>=100&n<100){write_add1(0);n++;}if(l>=100&n>=100){l=0;n=0;}p7=0;p5=1;p6=1;}void main(){uchar i,num,tab[2];//定义显示区域临时存储数组wc=0;num=0;tab[0]=0;tab[1]=0;TMOD=0x21;//设置定时器1为工作方式2定时器0为工作方式1 TH1=0xfd;TL1=0xfd;TR1=1;REN=1;SM0=0;SM1=1;EA=1;ES=1;init();init1();for(i=0;i<5;i++)num=read_add1(0);read_add(tab,1);sign=tab[0];ad=(uint)num*100;TH0=(65536-ad)/256;TL0=(65536-ad)%256;ET0=1; //定时器中断打开TR0=1;while(1){keyscan();for(i=0;i<5;i++)num=read_add1(0);voltage=500/num;ad=(uint)num*100;tab[0]=sign;tab[1]=ad;write_add(tab,1);num=read_add1(0);voltage=500/num;temp1[0]=voltage/100;temp1[1]=(voltage%100)/10;temp1[2]=voltage%1000;Display();}}void ser() interrupt 4{RI=0;sign=SBUF;}void T0_time() interrupt 1{ad=(uint)read_add1(0)*100;TH0=(65536-ad)/256;TL0=(65536-ad)%256;if(sign==1) sj(); if(sign==2) zx(); if(sign==3) fb(); }。
波形发生器是一种常用的信号源,广泛地应用于电子电路、自动控制系统和教学实验等领域。
本次课程设计使用的AT89S51 单片机构成的发生器可产生锯齿波、三角波、正弦波等多种波形,波形的周期可以用程序改变,并可根据需要选择单极性输出或双极性输出,具有线路简单、结构紧凑等优点。
在本设计的基础上,加上按钮控制和LED显示器,则可通过按钮设定所需要的波形频率,并在LED 上显示频率、幅值电压,波形可用示波器显示。
二、系统设计波形发生器原理方框图如下所示。
波形的产生是通过AT89S51 执行某一波形发生程序,向D/A转换器的输入端按一定的规律发生数据,从而在D/A转换电路的输出端得到相应的电压波形。
在AT89S51的P2口接5个按扭,通过软件编程来选择各种波形、幅值电压和频率,另有3个P2口管脚接TEC6122芯片,以驱动数码管显示电压幅值和频率,每种波形对应一个按钮。
此方案的有点是电路原理比较简单,实现起来比较容易。
缺点是,采样频率由单片机内部产生故使整个系统的频率降低。
1、波形发生器技术指标1)波形:方波、正弦波、锯齿波;2)幅值电压:1V、2V、3V、4V、5V;3)频率:10HZ、20HZ、50HZ、100HZ、200HZ、500HZ、1KHZ;2、操作设计1)上电后,系统初始化,数码显示6个…-‟,等待输入设置命令。
2)按钮分别控制“幅值”、“频率”、“方波”、“正弦波”、“锯齿波”。
3)“幅值“键初始值是1V,随后再次按下依次增长1V,到达5V后在按就回到1V。
4)“频率“键初始值是10HZ,随后在按下依次为20HZ、50HZ、100HZ、200HZ、500HZ、1000HZ循环。
三、硬件设计本系统由单片机、显示接口电路,波形转换(D/A)电路和电源等四部分构成。
电路图2附在后1、单片机电路功能:形成扫描码,键值识别、键处理、参数设置;形成显示段码;产生定时中断;形成波形的数字编码,并输出到D/A接口电路和显示驱动电路。
单片机产生正弦波
单片机产生正弦波可以通过使用数字信号合成技术来实现。
以下是一种常见的实现方法:
1. 首先,准备一个包含一周期正弦波的查表数组,数组长度为一个周期内所需的采样点数。
可以使用固定的采样频率(如
8kHz)和固定的振幅。
数组的内容为一个周期内的正弦波的
采样值,可以使用查表或者数学计算来生成。
2. 使用定时器产生固定的中断频率,生成一个固定的时间间隔,由于波形是连续的,通常采用中断的方式来生成波形。
3. 在每个定时器中断中,读取查表数组的对应位置的值,并通过DAC(数字到模拟转换器)输出到外部接口(如扬声器)。
4. 根据查表数组长度和定时器中断频率的选择,可以调整正弦波的频率(调整定时器中断频率)和振幅(调整查表数组中的采样值)。
需要注意的是,单片机的处理能力和外设的性能限制了可生成的最高频率,同时,由于数字信号合成存在理论上的误差,生成的波形可能并不完美。
因此,具体的实现方式还需要根据单片机型号和额外硬件资源来调整。
单片机产生正弦波一要求采用单片机map430g2553和运算放大器lmv358产生正弦波,周期1秒。
二思路可通过单片机产生PWM,调节参数寄存器的值,产生不同占空比的PWM信号。
若占空比的变化规律是正弦的,则滤波后可得到所需正弦波形。
其中,PWM(PulseWidthModulation)控制——脉冲宽度调制技术是通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形(含形状和幅值)。
图1为用PWM波代替正弦半波的例子。
(单片机输出图1b,滤波后得到图1a)图1用PWM三实践1PWM周期计算正弦波周期1秒,需要采用多少个周期的PWM况只有1个周期的PWM N=200个。
则PWM信号的周期为T=1/200秒=5毫秒。
2PWMPWM●ACLK、子系统主时钟SMCLK),ACLK由内部时钟源VLOCLK(低频时钟源,12K(默认1M赫兹)产生。
这里建议采用较高频率分频,这里设置为1分频,即ACLK=VLO;第二行中,SELM_0的作用是选择MCLK的时钟源为DCOCLK,DIVM_0设置为MCLK=DCO,DIVS_0设置为SMCLK=DCO(默认时钟源)。
TASSEL1将定时器时钟设置为SMCLK(若为TASSEL0则选择ACLK),且未分频。
模式选择MC_1为上升模式。
采用上述方法设置定时器时钟=SMCLK=DCO=1M赫兹。
●周期计数:上升模式表明定时器由0递增到一个上限值CCR0。
CCR0需设置。
因为周期T=1/200秒,而定时器时钟=SMCLK=DCO=1M赫兹,定时器周期t=1微秒,所以CCR0=T/t=5000,即5毫秒。
●高电平计数:定时器由0递增到一个上限值CCR0过程中,需设置脉宽CCR1。
并且K=CCR1/CCR0的数值每个周期(5毫秒)都变化一次,变化趋势满足正弦变化,200个5毫秒构成一个正弦变化周期。
为获得CCR1值,在matlab中输入:t=0:pi/100:2*pi;k=(sin(t)+1)/2;CCR1=round(4999*k);可获得201个CCR1值。
一、概述stm32单片机作为一种常用的微控制器,拥有丰富的外设资源,其中包括数字模拟转换器(DAC)模块。
DAC模块可以将数字信号转换为模拟信号,通常用于音频处理、波形生成等应用。
本次实践旨在利用stm32单片机的DAC模块,产生正弦波信号,并通过外部电路将其输出到示波器进行观测,验证其波形质量和稳定性。
二、实验准备1.硬件准备1)stm32开发板2)示波器3)示波器探头4)电路连线板5)杜邦线、电阻、电容等元件2.软件准备1)Keil开发环境2)stm32CubeMX配置工具三、实验步骤1.使用stm32CubeMX配置DAC模块1)在stm32CubeMX中新建工程,并选择对应型号的单片机2)在Pinout Configuration中配置DAC输出引脚3)在Configuration中使能DAC模块,并配置输出缓冲区、波形发生器等参数4)生成代码并导入Keil开发环境中2.编写DAC初始化和波形生成代码在Keil中编写初始化DAC模块的代码,并编写正弦波发生算法,将生成的正弦波数据写入DAC数据寄存器。
3.连接示波器进行观测1)通过电路连线板搭建DAC输出到示波器的电路连接2)将示波器探头连接到电路上,设置示波器参数4.程序烧录和调试使用ST-Link将程序烧录到stm32开发板中,通过示波器观测输出波形,并根据实际观测结果进行调试和优化。
五、实验结果与分析经实验验证,stm32DAC产生的正弦波信号波形质量良好,无明显畸变和波形失真,幅度和频率稳定。
示波器观测结果与理论预期吻合,在给定的频率和振幅下,输出波形符合正弦曲线特征。
实验结果表明,stm32DAC模块在波形生成方面具有较高的准确性和稳定性,适用于需要模拟信号输出的应用场景。
六、结论与展望本次实验通过对stm32DAC的使用实践,验证了其正弦波信号产生的可行性和稳定性。
未来可以进一步深入研究DAC模块的其他应用场景,并结合其他外设资源,实现更复杂的信号处理和控制功能。
单片机产生正弦波一要求采用单片机map430g2553和运算放大器lmv358产生正弦波,周期1秒。
二思路可通过单片机产生PWM,调节参数寄存器的值,产生不同占空比的PWM信号。
若占空比的变化规律是正弦的,则滤波后可得到所需正弦波形。
其中,PWM(Pulse Width Modulation)控制——脉冲宽度调制技术是通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形(含形状和幅值)。
图1为用PWM波代替正弦半波的例子。
(单片机输出图1b,滤波后得到图1a)图1 用PWM波代替正弦半波三实践1 PWM周期计算正弦波周期1秒,需要采用多少个周期的PWM信号去表示?数目过少,则波形不完整(极端状况只有1个周期的PWM);数目过多,则增加了单片机的计算量,并对速度有要求。
这里取N=200个。
则PWM信号的周期为T=1/200秒=5毫秒。
2 PWM参数计算PWM由定时器TimerA产生,参数主要包括:定时器时钟,周期计数,高电平计数三个。
●定时器时钟:定时器时钟来源有4个,两个内部的(辅助时钟ACLK、子系统主时钟SMCLK),两个外部的。
这里采用内部时钟。
没有外部晶体时,ACLK由内部时钟源VLOCLK(低频时钟源,12K赫兹)产生,SMCLK由内部数字时钟DCOCLK(默认1M赫兹)产生。
这里建议采用较高频率的。
部分代码如下:BCSCTL1 |= DIVA_0; // ACLK = VLOBCSCTL2 |= SELM_0 + DIVM_0 + DIVS_0; // MCLK = DCO, SMCLK = DCO // Configure TimerATACTL = TASSEL1 +MC_1; // Source: SMCLK, UP mode其中,ACLK可配置成VLOCLK的1,2,4,8分频,这里设置为1分频,即ACLK = VLO;第二行中,SELM_0的作用是选择MCLK的时钟源为DCOCLK,DIVM_0设置为MCLK = DCO,DIVS_0设置为SMCLK = DCO(默认时钟源)。
TASSEL1将定时器时钟设置为SMCLK(若为TASSEL0则选择ACLK),且未分频。
模式选择MC_1为上升模式。
采用上述方法设置定时器时钟= SMCLK = DCO = 1M赫兹。
●周期计数:上升模式表明定时器由0递增到一个上限值CCR0。
CCR0需设置。
因为周期T=1/200秒,而定时器时钟= SMCLK = DCO = 1M赫兹,定时器周期t=1微秒,所以CCR0=T/t=5000,即5毫秒。
●高电平计数:定时器由0递增到一个上限值CCR0过程中,需设置脉宽CCR1。
并且K= CCR1/ CCR0的数值每个周期(5毫秒)都变化一次,变化趋势满足正弦变化,200个5毫秒构成一个正弦变化周期。
为获得CCR1值,在matlab中输入:t=0:pi/100:2*pi;k=(sin(t)+1)/2;CCR1=round(4999*k);可获得201个CCR1值。
上式中,第一行设置了201个数,均匀分布在0-2pi 之间,第一个和最后一个分别对应0弧度和2pi弧度;第二行计算201个正弦值,偏置为0.5,全幅度为1的正弦波幅度,如图2所示:图2偏置为0.5,全幅度为1的正弦波幅度第三行计算CCR1值,为k与CCR0(这里是5000)的乘积,并取了四舍五入(round 函数)。
为将数据导出,便于单片机编程,在matlab中添加:fid = fopen('exp.txt','w');fprintf(fid,'%d,',CCR1);fclose(fid);则在matlab工作目录中生成了带逗号的连续CCR1值。
复制到程序中,定义一个数组temp[200],其数值为matlab生成的数值。
3 PWM实现流程程序包含两个中断,一个是定时器到达上限CCR0(这里是4999)时发出中断,并在中断服务程序中将输出置1,另一个是到达中间值CCR1(0至4999)时发出中断,并在中断服务程序中将输出置0。
考虑到同时发出中断时,会有中断嵌套问题、以及优先级问题,所以在当CCR1需置为4999时,手动置为4998。
软件流程如图3所示。
图3 软件流程图程序为://******************************************************************* ***********// LaunchPad Lab4 - Timer Toggle P1.6,//// MSP430G2553// -----------------// /|\| XIN|-// | | |// --|RST XOUT|-// | |// | P1.6|-->LED////******************************************************************* ***********#include<msp430g2553.h>shorttemp[200]={2500,2578,2656,2735,2813,2891,2968,3045,3121,3197,3272,334 6,3420,3492,3564,3634,3704,3772,3839,3904,3969,4031,4093,4152,4211,4267, 4322,4374,4425,4474,4522,4567,4610,4651,4690,4727,4761,4793,4823,4851,4877, 4900,4920,4939,4955,4968,4979,4988,4994,4998,4999,4998,4994,4988,4979,4968, 4955,4939,4920,4900,4877,4851,4823,4793,4761,4727,4690,4651,4610,4567,4522, 4474,4425,4374,4322,4267,4211,4152,4093,4031,3969,3904,3839,3772,3704,3634, 3564,3492,3420,3346,3272,3197,3121,3045,2968,2891,2813,2735,2656,2578,2500, 2421,2343,2264,2186,2108,2031,1954,1878,1802,1727,1653,1579,1507,1435,1365, 1295,1227,1160,1095,1030,968,906,847,788,732,677,625,574,525,477,432,389,34 8,309,272,238,206,176,148,122,99,79,60,44,31,20,11,5,1,0,1,5,11,20,31,44,60 ,79,99,122,148,176,206,238,272,309,348,389,432,477,525,574,625,677,732,788,8 47,906,968,1030,1095,1160,1227,1295,1365,1435,1507,1579,1653,1727,1802,1878, 1954,2031,2108,2186,2264,2343,2421};int i=0;void main(void){WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timerif (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF){while(1); // If calibration constants erased, trap CPU!!}BCSCTL1 = CALBC1_1MHZ; // Set rangeDCOCTL = CALDCO_1MHZ; // Set DCO step + modulationBCSCTL3 |= LFXT1S_2; // LFXT1 = VLOP1DIR = 0x40; // P1.6 output (green LED) P1OUT = 0; // LED offIFG1 &= ~OFIFG; // Clear OSCFault flagBCSCTL1 |= DIVA_0; // ACLK = VLOBCSCTL2 |= SELM_0 + DIVM_0 + DIVS_0; // MCLK = DCO, SMCLK = DCO// Configure TimerATACTL = TASSEL1 +MC_1; // Source: ACLK, UP modeCCR0 = 5000; //Timer count 5100CCR1 = 2500; //Timer count 100CCTL0 = CCIE; //CCR0 interrupt enabledCCTL1 = CCIE; //CCR1 interrupt enabled_BIS_SR(GIE);for(;;);}// Timer A0 interrupt service routine#pragma vector=TIMER0_A0_VECTOR__interrupt void Timer_A0 (void){P1OUT |= BIT6; // P1.6 output Highif(i==199){i=0;}else{i++;}if(temp[i]==4999){CCR1=4998;}else{CCR1=temp[i];}}// Timer A1 Interrupt Vector (TA0IV) handler#pragma vector=TIMER0_A1_VECTOR__interrupt void Timer_A1(void){switch( TA0IV ){case 2: P1OUT &= ~BIT6; // P1.6 output Low break;case 10:break;}}4 输出滤波输出运放采用lmv358。
其管脚如下图4所示:图4 358管脚示意图采用压控电压源二阶低通滤波电路。
(参考《模拟电子技术基础》,第三版,童诗白、华成英主编,7.4.2节,352页)。
其电路图如图5所示:图5 压控电压源二阶低通滤波电路通带增益:A vp=1+R 4/R 3传递函数:所需设计的滤波器输出为1赫兹的正弦波,放大倍数为1,所以设置截止频率为f0=10。
取增益A vp=1,即R 4=0,R 3= R 2= R 1= R.C1=C.取f0=1/( 2πRC),则RC= 0.015915494309189533576888376337251。