单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 78|回复: 0
收起左侧

51单片机波形发生器程序设计及Proteus仿真

[复制链接]
飞啊飞啊 发表于 2019-9-12 16:06 | 显示全部楼层 |阅读模式
如题,内容包括protuce仿真及源程序两部分
一、 作品简介:可以通过按键控制STC89C52单片机输出[url=]不同波形[/url][z1] 信号。通过usb给pcb板通5v的电压可以发出方波,三角波,锯齿波,正弦波并在LCD显示屏上显示波形类别,频率和幅值。通过按键可调波形类别,可调节频率步进值有1Hz,10Hz和50Hz。最低频率为10Hz最高频率为800Hz。
  
  
二、设计原理:将各种波形的每个周期平均分成255份,把每份的值依次发给P0口,每份的时间间隔通过开启定时器0来控制,当定时时间到时单片机就产生中断,在中断服务程序里面通过P0口将每份的值发出去,这个值通过向D/A换器的输入端按一定的规律发生数据,从而在转换电路的输出端得到相应的电压波形。
  
  
三、    功能说明:能够产生方波、锯齿波、三角波、正弦波信号的波形发生器
  
(1)  按键选择波形。按键控制单片机输出方波、锯齿波、三角波或者正弦波信号。按键K1,K2,K3,K4改变波形类型,K5,K6控制频率的加减。
  
(2)  波形参数显示。通过液晶屏显示单片机当前输出波形的频率、幅度。
  
(3)  频率调节。通过外部按键,调节单片机输出波形信号的频率。

0.png

单片机源程序如下:

  1. /****************************************************************************************************************/
  2. /*                                           简易波形发生器 程序                                                */
  3. /*                                            编写者 :FHX                                                      */
  4. /*                                  可输出 正弦波 三角波 方波  按键控制波形、频率、步进值                       */
  5. /*                            由于是单片机定时器控制频率   经测试频率只能在10HZ ~ 700HZ 之间                    */
  6. /*                            有掉电储存功能 再次上电时 显示掉电前设置好的波形 频率 步进值                      */               
  7. /****************************************************************************************************************/

  8. #include "lcd12864.h"
  9. #include "key.h"
  10. #include "24c02.h"
  11. #include "function.h"

  12. uchar T1RH = 0;                                //定时器1重载值高位
  13. uchar T1RL = 0;                                //定时器1重载值低位

  14. uchar T0RH = 0;                                //定时器0重载值高位
  15. uchar T0RL = 0;                                //定时器0重载值低位
  16. uchar mode = 0;
  17. sbit led=P2^4;
  18. sbit led1=P2^7;
  19. extern uchar Wave_Index;                       //声明 波形变量

  20. uchar code sin[32]={                                             //此数组内的数据为,DA输出对应电压值对应的数字量,0是0V,255是5V
  21.         127, 152, 176, 198, 217, 233, 245, 252,
  22.   255, 252, 245, 233, 217, 198, 176, 152,
  23.   127, 102, 78, 56, 37, 21, 9, 2,
  24.   0, 2, 9, 21, 37, 56, 78, 102

  25. };                                          //正弦波取码
  26. uchar code juxing[32]={                                                 //一个周期是采样32个点, 所以数组内是32个数据
  27.         255,255,255,255,255,255,255,255,255,255,
  28.   255,255,255,255,255,255,0,0,0,0,0,0,0,0,
  29.         0,0,0,0,0,0,0,0
  30. };                                          //矩形波取码

  31. uchar code sanjiao[32]={
  32.         0, 16, 32, 48, 64, 80, 96, 112,
  33.   128, 144, 160, 176, 192, 208, 224, 240,
  34.   255, 240, 224, 208, 192, 176, 160, 144,
  35.   128, 112, 96, 80, 64, 48, 32, 16

  36. };                                                //三角波取码
  37. uchar code jvchi[32]={
  38.         0, 16, 32, 48, 64, 80, 96, 112,
  39.   128, 144, 160, 176, 192, 208, 224, 240,
  40.   255, 0, 16, 32, 48, 64, 80, 96, 112,
  41.   128, 144, 160, 176, 192, 208, 224

  42. };                                                //锯齿波取码


  43. /*****************子函数声明*****************/
  44. void Timer1Init(uint ms);
  45. void SetWaveRate(uint num_2);
  46. void Control_Key();
  47. void Refresh_Out();
  48. /*****************************************************************************/
  49. /*                                 主函数                                    */
  50. /*****************************************************************************/
  51. void main()
  52. {        led=1;
  53.     led1=1;
  54.         Timer1Init(1);                          //初始化定时器1 定时1ms
  55.         LcdInit();                              //初始化12864
  56.         Init_Display();                         //显示固定内容
  57.         Init_OutPut();                          //初始化输出数据和显示

  58.         while(1)
  59.         {
  60.                 Refresh_Out();                        //更新输出 mode=0:输出波形 独立按键关闭 mode!=0 :关闭波形输出 可用独立按键调整
  61.                 Control_Key();                        //控制独立按键 调整模式mode
  62.                 KeyDrive();                                                                      //调整波形、频率及步进值
  63.         }
  64. }

  65. /*****************************************************************************/
  66. /*                             按键控制函数                                  */
  67. /*               按键KEY_1 :用延时函数判断按下 控制模式变换                  */
  68. /*****************************************************************************/
  69. void Control_Key()
  70. {
  71.         if(KEY_1==0)                            //按下按键1  mode+1
  72.         {
  73.                 DelayMs(2);
  74.                 if(KEY_1==0)
  75.                 {
  76.                         while(!KEY_1);
  77.                         mode++;                              
  78.                         if(mode > 3)mode = 1;
  79.                 }
  80.         }
  81. }

  82. /*****************************************************************************/
  83. /*                            更新输出函数                                   */
  84. /*                      根据不同的模式变量 打开或关闭波形输出                */
  85. /*****************************************************************************/
  86. void Refresh_Out()
  87. {
  88.                         if(mode == 0)                                    //不显示箭头   输出波形 独立按键关闭
  89.                   {
  90.                                 ET1=0;
  91.                           TR1=0;
  92.                           ET0=1;       
  93.               TR0=1;
  94.                     EA=1;
  95.                           Display_Arr(0);
  96.                   }
  97.                
  98.                   else if(mode == 1)                               //箭头指向 "波形"   说明是在切换波形
  99.                   {
  100.                                 ET1=1;
  101.               TR1=1;
  102.                           ET0=0;       
  103.               TR0=0;
  104.                           EA=1;
  105.                           Display_Arr(1);
  106.                   }
  107.                
  108.                   else if(mode == 2)                               //箭头指向 "频率"   说明是在加减频率
  109.                   {
  110.                                 ET1=1;
  111.                           TR1=1;
  112.                           ET0=0;       
  113.               TR0=0;
  114.                     EA=1;
  115.                           Display_Arr(2);
  116.                   }
  117.                
  118.                   else if(mode == 3)                               //箭头指向 "步进值" 说明在加减步进值
  119.                   {
  120.                                 ET1=1;
  121.                           TR1=1;
  122.                           ET0=0;       
  123.               TR0=0;
  124.                     EA=1;
  125.                           Display_Arr(3);
  126.                   }
  127. }


  128. /*****************************************************************************/
  129. /*                             按键动作函数                                  */
  130. /*          按键  KEY_2 ~ KEY_4 三个按键由定时器1中断扫描 有长按功能         */
  131. /*****************************************************************************/
  132. void KeyDown(uchar keycode)
  133. {
  134.         /*********************************/
  135.         /*            "+"键              */
  136.         /*********************************/       
  137.         if(keycode == 0x26)                          
  138.         {
  139.                 if(mode == 1)                                    //模式1 向右切换波形
  140.                 {
  141.                         Convert_Wave(1);
  142.                 }
  143.                
  144.                 else if(mode == 2)                               //模式2 增加频率
  145.                 {
  146.                         Change_Rate(1);
  147.                 }
  148.                
  149.                 else if(mode == 3)                               //模式3 增加步进值
  150.                 {
  151.                         Change_Step(1);
  152.                 }
  153.   }
  154.         /*********************************/
  155.         /*            "-"键              */
  156.         /*********************************/
  157.         else if(keycode == 0x28)                           
  158.         {
  159.                 if(mode == 1)                                    //模式1 向左切换波形
  160.                 {
  161.                         Convert_Wave(0);
  162.                 }
  163.                
  164.                 else if(mode == 2)                               //模式2 减小频率
  165.                 {
  166.                         Change_Rate(0);
  167.                 }
  168.                
  169.                 else if(mode == 3)                               //模式3 减小步进值
  170.                 {
  171.                         Change_Step(0);     
  172.                 }
  173.         }
  174.         /*********************************/
  175.         /*          模式清零键           */
  176.         /*********************************/       
  177.         else if(keycode == 0x0D)
  178.         {
  179.                 mode = 0;
  180.         }
  181. }



  182. /**********频率设置函数****************/
  183. /************定时器0控制***************/
  184. void SetWaveRate(uint num_2)
  185. {
  186.         ulong tmp;                                             
  187.         tmp=(12000000/12)/(num_2*32);                            //定时器计数频率 是波形频率的32倍                                                                        
  188.         tmp=65536-tmp;                                           //计算定时器重载值                        
  189.   tmp=tmp+18;                                              //补偿
  190.         T0RH=(uchar)(tmp>>8);                                    
  191.         T0RL=(uchar)tmp;
  192.         TMOD&=0xF0;                                          
  193.         TMOD|=0x01;                                          
  194.         TH0=T0RH;                                             
  195.         TL0=T0RL;
  196. }

  197. /**********定时器1初始化函数***********/
  198. /**********用于三个独立按键扫描********/
  199. void Timer1Init(uint ms)
  200. {
  201.         ulong tmp;                                               //16位长整型变量tmp
  202.         tmp=12000000/12;                                         //用晶振频率除以12得到定时器计数频率
  203.         tmp=(tmp*ms)/1000;                                       //计算出需要多少个机器周期
  204.         tmp=65536-tmp;                                           //定时器的重载值
  205.         tmp=tmp+28;                                              //补偿中断延时响应造成的误差
  206.         T1RH=(uchar)(tmp>>8);                                    //将tmp高8位右移8位 赋值给T1RH
  207.         T1RL=(uchar)tmp;                                         //将tmp低8位赋值给T0RL
  208.         TMOD&=0x0F;                                              //清零T1控制位
  209.         TMOD|=0x10;                                              //选择模式1

  210. }

  211. /**********定时器0中断函数**********/
  212. /*******输出相应频率的波形数据******/
  213. void InterruptTimer0() interrupt 1
  214. {
  215.         static uchar cnt;                                               //变量 用于输出波形采样点
  216.         TH0=T0RH;
  217.         TL0=T0RL;
  218.         switch(Wave_Index)
  219.         {
  220.                 case 0:DAC_OUT=sin[cnt];break;
  221.                 case 1:DAC_OUT=sanjiao[cnt];break;
  222.                 case 2:DAC_OUT=juxing[cnt];break;
  223.         }
  224.         cnt++;
  225.         if(cnt>=32)cnt=0;
  226. }

  227. void InterruptTimer1() interrupt 3
  228. {
  229.         TH1=T1RH;                                                //重载初值
  230.         TL1=T1RL;
  231.   KeyScan();                                               //按键扫描
  232. }
复制代码

所有资料51hei提供下载:
仿真及程序.rar (98.29 KB, 下载次数: 4)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51Hei单片机16群 联系QQ:125739409;技术交流QQ群7344883

Powered by 单片机教程网

快速回复 返回顶部 返回列表