Simulation design of signal generator based on 51 microcontroller

Simulation design based on 51 microcontroller signal generator

(Simulation + program source code + design instructions + explanation video)

Original version of simulation: proteus 7.8

Program compiler: keil 4/keil 5

Programming language: C language

Design number: S0015

1 Design description:

1. This design uses AT89C51 microcontroller as the control core, and the peripheral uses digital/analog conversion circuit (DAC0832), operational amplifier circuit (LM324), buttons and LCD1602 liquid crystal display circuit.

2. The circuit uses a microcontroller and a DAC0832 digital-to-analog converter to form a digital low-frequency signal generator, which can generate four waveforms: sine wave, rectangular wave, sawtooth wave and triangle wave.

3. Use the keyboard to control the type selection and frequency changes of the four waveforms, and display their respective waveform types and frequency values ​​through the LCD 1602.

This design has simple hardware circuit, complete software functions, reliable control system, high cost performance, and has certain practical and reference value.

2 Explanation video:

Contains program explanation and code explanation

3 Simulation circuit:

imgimgimgimg

program

image-20220903210034666
Part of the code

uchar code tosin[256]=
{
    
    0x80,0x83,0x86,0x89,0x8d,0x90,0x93,0x96,0x99,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,
0xae,0xb1,0xb4,0xb7,0xba,0xbc,0xbf,0xc2,0xc5,0xc7,0xca,0xcc,0xcf,0xd1,0xd4,0xd6,0xd8,
0xda,0xdd,0xdf,0xe1,0xe3,0xe5,0xe7,0xe9,0xea,0xec,0xee,0xef,0xf1,0xf2,0xf4,
0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,
0xf4,0xf2,0xf1,0xef,0xee,0xec,0xea,0xe9,0xe7,0xe5,0xe3,0xe1,0xde,0xdd,0xda,0xd8,
0xd6,0xd4,0xd1,0xcf,0xcc,0xca,0xc7,0xc5,0xc2,0xbf,0xbc,0xba,0xb7,0xb4,0xb1,0xae,0xab,
0xa8,0xa5,0xa2,0x9f,0x9c,0x99,0x96,0x93,0x90,0x8d,0x89,0x86,0x83,0x80,
0x80,0x7c,0x79,0x76,0x72,0x6f,0x6c,0x69,0x66,0x63,0x60,0x5d,0x5a,0x57,0x55,
0x51,0x4e,0x4c,0x48,0x45,0x43,0x40,0x3d,0x3a,0x38,0x35,0x33,0x30,0x2e,0x2b,
0x29,0x27,0x25,0x22,0x20,0x1e,0x1c,0x1a,0x18,0x16,0x15,0x13,0x11,0x10,0x0e,
0x0d,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x02,0x01,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02 ,0x02,0x03,0x04,
0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0d,0x0e,0x10,0x11,0x13,0x15,0x16,0x18,
0x1a,0x1c,0x1e,0x20,0x22,0x25,0x27,0x29,0x2b,0x2e,0x30,0x33,0x35,0x38,0x3a,
0x3d,0x40,0x43,0x45,0x48,0x4c,0x4e ,0x51,0x55,0x57,0x5a,0x5d,0x60,0x63,0x66 ,
0x69,0x6c,0x6f,0x72,0x76,0x79,0x7c,0x80 }; //正弦波码 128取值到256

//--延时MS
void DelayMS(uchar ms)
{
    
    
	uchar i;
	while(ms--) for(i=0;i<120;i++);
}
//--延时y*9us
 void Delay1(uint y)
 {
    
    
 	uint i;
	for(i=y;i>0;i--);
 }
//-------------
//忙检查
//-----------------------------
uchar Busy_Check()
{
    
    
	uchar LCD_Status;
	RS=0;  //	寄存器选择
	RW=1; //读状态寄存器
	EN=1;  // 开始读
	DelayMS(1);
	LCD_Status=P1;
	EN=0;
	return  LCD_Status;

}
//----------------------------
//写LCD命令
//---------------------------------
void Write_LCD_Command(uchar cmd)
{
    
    
	   while((Busy_Check()&0x80)==0x80);   //忙等待
	   RS=0;  //选择命令寄存器
	   RW=0;  //写
	   EN=0;
	   P1=cmd;EN=1;DelayMS(1);EN=0;
}										  
//--------------------------------------
//发送数据
//---------------------------------------
void Write_LCD_Data(uchar dat)
{
    
    
	 while((Busy_Check()&0x80)==0x80);   //忙等待	
	  RS=1;  RW=0; EN=0; P1=dat;EN=1;DelayMS(1);EN=0;	
}
//------------------------------------
//LCD初始化			   
//-----------------------------------------
void Init_LCD()
{
    
    		
	Write_LCD_Command(0x38);
	DelayMS(1);
	Write_LCD_Command(0x01); //清屏
	DelayMS(1);
	Write_LCD_Command(0x06); //字符进入模式:屏幕不动,字符后移
	DelayMS(1);
	Write_LCD_Command(0x0C); //显示开、关光标
	DelayMS(1);
}

//--向LCD写频率值
void Write_freq(uint k)
{
    
    
	uchar qian,bai,shi,ge;
	qian=k/1000;
	bai=k/100%10;
	shi=k/10%10;
	ge=k%10;
	Write_LCD_Command(0x86+0x40);
	Write_LCD_Data(0x30+qian);
	Write_LCD_Data(0x30+bai);
	Write_LCD_Data(0x30+shi);
	Write_LCD_Data(0x30+ge);
	Write_LCD_Data(0x48);
	Write_LCD_Data(0x5a);
}

 //--LCD上显示不同波形频率
  void Xianshi_f()		   
{
    
    
  if(WaveChoice==1)
  {
    
    
     freq=(10000000/(50000+2860*ys));
	 Write_freq(freq);
  }
  if(WaveChoice==2)
  {
    
    
     freq=(10000000/(50000+2300*ys));
	 Write_freq(freq);
  }
   if(WaveChoice==3)
  {
    
    
     freq=(10000000/(14000+2300*ys));
	 Write_freq(freq);
  }
    if(WaveChoice==4)
  {
    
    
     freq=(10000000/(15000+2300*ys));
	 Write_freq(freq);
  }
}
//--LCD上写波形类型
void Write_wave(uchar  t )
{
    
    
	switch(t)
	{
    
    
		case 0:
				//-- 无输出
				 Write_LCD_Command(0x86);
  				 DelayMS(5);
   				 for (i=0;i<sizeof(No)-1;i++)
					{
    
    
						Write_LCD_Data(No[i]);
						DelayMS(5);
					}
					break;
		case 1:
				//--正弦波
				ys=25;
				Write_LCD_Command(0x86);
  				 DelayMS(5);
   				 for (i=0;i<sizeof(Sin)-1;i++)
					{
    
    
						Write_LCD_Data(Sin[i]);
						DelayMS(5);
					}
				break;
		case 2:
				//---矩形波
				ys=30;
				Write_LCD_Command(0x86);
  				 DelayMS(5);
   				 for (i=0;i<sizeof(Squ)-1;i++)
					{
    
    
						Write_LCD_Data(Squ[i]);
						DelayMS(5);
					 }
			
				break;
		case 3:
				//---三角波
				ys=30;
				Write_LCD_Command(0x86);
  				 DelayMS(5);
   				 for (i=0;i<sizeof(Tri)-1;i++)
					{
    
    
						Write_LCD_Data(Tri[i]);
						DelayMS(5);
					}
				break;
		case 4:
				//----锯齿波
				ys=30;
			  	 Write_LCD_Command(0x86);//液晶显示位置
  				 DelayMS(5);
   				 for (i=0;i<sizeof(Saw)-1;i++)
					{
    
    
						Write_LCD_Data(Saw[i]);
						DelayMS(5);
					 }
				break;
	}
}
//---输出波形
void Out_Wave(uchar i)
{
    
    	 uchar j;	
	switch(i)
	{
    
    
		case 0:	P0=0x00;break;
		case 1:
				//---正弦波
				for (j=0;j<255;j++)
				{
    
    
					P0=tosin[j];
					Delay1(ys);
				} 
				 break;
		case 2:
				//----矩形波 相当于写0和写1
				{
    
    
					if(a<sqar_num)
						{
    
    
							P0=0xff;
							Delay1(ys);//改变周期
						}
					else  
						{
    
    
							P0=0x00;
							Delay1(ys);
						}
						a++;
				}  break;
		case 3:
				//----三角波//数值的递加和递减
				{
    
    
					if(a<128) 
						{
    
    
							P0=a;
							Delay1(ys);
						}
					else  
						{
    
    
							P0=255-a;
							Delay1(ys);
						}
						a++;
				}   break;
		case 4:
			   //----锯齿波//数值的递增和归零
				{
    
    
		 			if(a<255)
					{
    
    
						P0=a;
						Delay1(ys);
					}
				
				a++;
			if(a==255)
				{
    
    
					a=0;
				}   break;
		}
	}
}
//----按键扫描
void keyscanf()
{
    
    	
	if(K2==0)
	{
    
    
		DelayMS(5);
		if(K2==0)
		{
    
    
			while(!K2);
			ys--;
			if(ys==0)
			ys=20;
		}
	}
	if(K3==0)
	{
    
    
		DelayMS(5);
		if(K3==0)
		{
    
    
			while(!K3);
			ys++;
			if(ys>22)
			ys=20;
		}
	}
	if(K4==0)
	{
    
    
		DelayMS(5);
		if(K4==0)
		{
    
    
			while(!K4);
			if(WaveChoice==2)
			sqar_num=sqar_num+2;
			if(sqar_num==238)
				sqar_num=128;
		}
	}
	if(K5==0)
	{
    
    
		DelayMS(5);
		if(K5==0)
		{
    
    
			while(!K5);
			if(WaveChoice==2)
			sqar_num=sqar_num-2;
			if(sqar_num==18)
				sqar_num=128;			
		}
	}
} 

//----主程序--- 
void main()
{
    
    
	Init_LCD();
	IE=0X81;
	IT0=1;
	Write_LCD_Command(0x80);//--显示wave:
   	DelayMS(5);	 	
   for (i=0;i<sizeof(Wave)-1;i++)
		{
    
    
			Write_LCD_Data(Wave[i]);
			DelayMS(5);
		}
   	 Write_LCD_Command(0x80+0X40);//----显示freq:
     DelayMS(5);
    for (i=0;i<sizeof(Fre)-1;i++)
		{
    
    
			Write_LCD_Data(Fre[i]);
			DelayMS(5);
		}
	   Write_wave(WaveChoice);
	while (1)
	{
    
    
			 keyscanf();
		Out_Wave(WaveChoice);
		if(!(K1&K2&K3))
				Xianshi_f();
	}	  
}

Programming flow chart

img

LCD1602 display

//----------------------------
//写LCD命令
//---------------------------------
void Write_LCD_Command(uchar cmd)
{
	   while((Busy_Check()&0x80)==0x80);   //忙等待
	   RS=0;  //选择命令寄存器
	   RW=0;  //写
	   EN=0;
	   P1=cmd;EN=1;DelayMS(1);EN=0;
}										  
//--------------------------------------
//发送数据
//---------------------------------------
void Write_LCD_Data(uchar dat)
{
	 while((Busy_Check()&0x80)==0x80);   //忙等待	
	  RS=1;  RW=0; EN=0; P1=dat;EN=1;DelayMS(1);EN=0;	
}
//------------------------------------
//LCD初始化			   
//-----------------------------------------
void Init_LCD()
{		
	Write_LCD_Command(0x38);
	DelayMS(1);
	Write_LCD_Command(0x01); //清屏
	DelayMS(1);
	Write_LCD_Command(0x06); //字符进入模式:屏幕不动,字符后移
	DelayMS(1);
	Write_LCD_Command(0x0C); //显示开、关光标
	DelayMS(1);
}

//--向LCD写频率值
void Write_freq(uint k)
{
	uchar qian,bai,shi,ge;
	qian=k/1000;
	bai=k/100%10;
	shi=k/10%10;
	ge=k%10;
	Write_LCD_Command(0x86+0x40);
	Write_LCD_Data(0x30+qian);
	Write_LCD_Data(0x30+bai);
	Write_LCD_Data(0x30+shi);
	Write_LCD_Data(0x30+ge);
	Write_LCD_Data(0x48);
	Write_LCD_Data(0x5a);
}

 //--LCD上显示不同波形频率
  void Xianshi_f()		   
{
  if(WaveChoice==1)
  {
     freq=(10000000/(50000+2860*ys));
	 Write_freq(freq);
  }
  if(WaveChoice==2)
  {
     freq=(10000000/(50000+2300*ys));
	 Write_freq(freq);
  }
   if(WaveChoice==3)
  {
     freq=(10000000/(14000+2300*ys));
	 Write_freq(freq);
  }
    if(WaveChoice==4)
  {
     freq=(10000000/(15000+2300*ys));
	 Write_freq(freq);
  }
}
//--LCD上写波形类型
void Write_wave(uchar  t )
{
	switch(t)
	{
		case 0:
				//-- 无输出
				 Write_LCD_Command(0x86);
  				 DelayMS(5);
   				 for (i=0;i<sizeof(No)-1;i++)
					{
						Write_LCD_Data(No[i]);
						DelayMS(5);
					}
					break;
		case 1:
				//--正弦波
				ys=25;
				Write_LCD_Command(0x86);
  				 DelayMS(5);
   				 for (i=0;i<sizeof(Sin)-1;i++)
					{
						Write_LCD_Data(Sin[i]);
						DelayMS(5);
					}
				break;
		case 2:
				//---矩形波
				ys=30;
				Write_LCD_Command(0x86);
  				 DelayMS(5);
   				 for (i=0;i<sizeof(Squ)-1;i++)
					{
						Write_LCD_Data(Squ[i]);
						DelayMS(5);
					 }
			
				break;
		case 3:
				//---三角波
				ys=30;
				Write_LCD_Command(0x86);
  				 DelayMS(5);
   				 for (i=0;i<sizeof(Tri)-1;i++)
					{
						Write_LCD_Data(Tri[i]);
						DelayMS(5);
					}
				break;
		case 4:
				//----锯齿波
				ys=30;
			  	 Write_LCD_Command(0x86);//液晶显示位置
  				 DelayMS(5);
   				 for (i=0;i<sizeof(Saw)-1;i++)
					{
						Write_LCD_Data(Saw[i]);
						DelayMS(5);
					 }
				break;
	}
}

Key scan

//----按键扫描
void keyscanf()
{	
	if(K2==0)
	{
		DelayMS(5);
		if(K2==0)
		{
			while(!K2);
			ys--;
			if(ys==0)
			ys=20;
		}
	}
	if(K3==0)
	{
		DelayMS(5);
		if(K3==0)
		{
			while(!K3);
			ys++;
			if(ys>22)
			ys=20;
		}
	}
	if(K4==0)
	{
		DelayMS(5);
		if(K4==0)
		{
			while(!K4);
			if(WaveChoice==2)
			sqar_num=sqar_num+2;
			if(sqar_num==238)
				sqar_num=128;
		}
	}
	if(K5==0)
	{
		DelayMS(5);
		if(K5==0)
		{
			while(!K5);
			if(WaveChoice==2)
			sqar_num=sqar_num-2;
			if(sqar_num==18)
				sqar_num=128;			
		}
	}
} 

main function

//----主程序--- 
void main()
{
	Init_LCD();
	IE=0X81;
	IT0=1;
	Write_LCD_Command(0x80);//--显示wave:
   	DelayMS(5);	 	
   for (i=0;i<sizeof(Wave)-1;i++)
		{
			Write_LCD_Data(Wave[i]);
			DelayMS(5);
		}
   	 Write_LCD_Command(0x80+0X40);//----显示freq:
     DelayMS(5);
    for (i=0;i<sizeof(Fre)-1;i++)
		{
			Write_LCD_Data(Fre[i]);
			DelayMS(5);
		}
	   Write_wave(WaveChoice);
	while (1)
	{
			 keyscanf();
		Out_Wave(WaveChoice);
		if(!(K1&K2&K3))
				Xianshi_f();
	}	  
}

This system uses programming methods to output four different waveforms, namely sine wave, rectangular wave, triangle wave, and sawtooth wave. The various waveforms are generated as follows.

Sine wave generation subroutine

The generation of sine wave is quite special. It cannot be directly generated by a microcontroller. It can only be approximated to a sine wave by a staircase wave as shown in Figure 17. Obviously, the more steps there are in a cycle, the closer the waveform output by the microcontroller will be to a sine wave.

img

Figure 17 Generation of sine wave signal

Assume first that the amplitude of the sine wave is 2.56 V, then the digital quantity corresponding to the trough is the minimum value 00H, and the digital quantity corresponding to the crest is the maximum value FFH. Divide the waveform of the first cycle of the sine wave into several equal parts according to the angle, and calculate the voltage value corresponding to each point. The voltage value calculation method is: Vx=2.5·(1+sinθ), because 00H~FFH corresponds to The digital quantity is 0~255, so the digital quantity corresponding to each point can be written directly based on the calculated voltage. The microcontroller stores the digital quantities of one cycle into a certain storage area, then cycles out these digital quantities in sequence, and sends them to the D/A circuit to convert them into a staircase wave, that is, an approximate sine wave output. Figure 18 is a flow chart of sine wave generation.

img

Figure 18 Flow chart of sine wave generation

Rectangular wave generation subroutine

As shown in Figure 19, the implementation of rectangular wave is relatively simple. First, define an unsigned character variable i=0, so that the independent variable i continuously increases by 1. If the value of i is less than squa_num, assign the P0 port to 0xFF; if the value of i is greater than squa_num, assign the P0 port to 0x00. . When i increases to 256, it automatically changes to 0. In this cycle, a rectangular wave can be obtained. When squa_num=128, the output is a square wave. By adjusting the size of squa_num, the duty cycle of the rectangular wave can be adjusted; by adjusting the delay time, the frequency of the rectangular wave can be changed.

img

Figure 19 Rectangular wave generation flow chart

Triangular wave generation subroutine

The slope in the triangular wave is approximated by small steps. When the step intervals are small, the waveform basically approximates a straight line. First define an unsigned character variable i=0, so that the independent variable i continuously increases by 1. If the value of i is less than 128, the P0 port is assigned the value i; if the value of i is greater than 128, the P0 port is assigned the value 256. -i. When i is added to 256, it automatically changes to 0, and the cycle continues, so that the P0 port realizes periodic digital transformation. After digital-to-analog conversion, it is converted into an analog signal. After being passed through the operational amplifier circuit, the periodicity is obtained. triangle wave. The triangular wave generation flow chart is shown in Figure 20.

img

Figure 20 Triangular wave generation flow chart

Sawtooth wave generation subroutine

The implementation process of the sawtooth wave is similar to that of the triangle wave. It also defines a variable i=0 and makes P0=i. The independent variable i continues to automatically increase by 1 until it reaches 255, and then i can automatically return to 0, and then continue to repeat. on process. During this process, the value of port P0 also changes with i. After digital-to-analog conversion DAC0832, the digital quantity that changes periodically one by one is converted into a sawtooth wave output. By adjusting the delay time between each two adjacent values ​​of the P0 port, the frequency of the sawtooth wave can be changed. Figure 21 is a flow chart of sawtooth wave generation.

img

Figure 21 Sawtooth wave generation flow chart

design manual

image-20231026123744873

Required Required

Signal generator is a commonly used signal source, widely used in electronic circuits, automatic control systems, teaching experiments and other fields. This design uses AT89C51 microcontroller as the control core, and the peripheral uses digital/analog conversion circuit (DAC0832), operational amplifier circuit (LM324), button and LCD liquid crystal display circuit. The circuit uses a microcontroller and a DAC0832 digital-to-analog converter to form a digital low-frequency signal generator, which can generate four waveforms: sine wave, rectangular wave, sawtooth wave and triangle wave. The system generates digital signals through the microcontroller, converts them into analog signals through DAC0832, and then obtains various bipolar waveforms through the amplifier LM324, which are finally displayed by the oscilloscope. The type selection and frequency changes of the four waveforms are controlled through the keyboard, and their respective waveform types and frequency values ​​are displayed through the LCD 1602.

This design has simple hardware circuit, complete software functions, reliable control system, high cost performance, and has certain practical value and reference value.

Keywords: AT89C51 microcontroller; function signal generator; DAC0832; LCD liquid crystal display

Material list&&download link

0. Frequently Asked Questions. Must read! ! ! !
1. Source program
2. Proteus simulation
3. Project proposal report
4. Thesis report
5. Explanation video
Altium Designer installation and cracking
filename.bat
KEIL +proteus microcontroller simulation design tutorial
KEIL installation and cracking
Proteus component search
Proteus installation
Proteus simple use tutorial
Microcontroller learning materials
Related data manuals
Defense skills
Design Common descriptions of reports
Double-click to open the search for Jiasheng Microcontroller 51 STM32 Microcontroller Course Graduation Project.url

image-20231026123822944

Data download link

Guess you like

Origin blog.csdn.net/weixin_52733843/article/details/134635616