找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 9581|回复: 3
打印 上一主题 下一主题
收起左侧

51单片机的多波形发生器设计(PCF8591)源程序 正弦波、三角波、锯齿波、方波、梯形波

  [复制链接]
跳转到指定楼层
楼主
多波形发生器基本功能:
1、可产生多种波形,如正弦波、三角波、锯齿波、方波、梯形波等;
2、各种波形可通过按键选择;
3、可调节信号的频率参数。

1方案论证与对比
1.1     方案1

利用STC89C52RC为硬件核心,STC89C52RC具有8KB ROM存储空间,512字节数据存储空间,带有MCS-51系列单片机完全兼容,STC89C52RC可以通过串口下载。本次实验设计采用单片机的PCF8591硬件接口实现D/A数模转换设计。PCF8591时一个单电源低功耗的8位CMOS数据采集器件,具有4路模拟输入,1路模拟输出和一个串行I2C总线接口用来与单片机通信,符合电路简单,方便查找错误的设计理念。


2硬件电路设计

仔细分析课题后,并查找了相应资料,所学单片机中有关矩阵按键、A/D模数和D/A数模转换的有关知识,设计出整体硬件原理框图如图1所示, 其中晶振通过自身振荡为单片机系统提供基准时钟信号,复位电路用于单片机复位,矩阵按键控制波形、频率切换。

      

图1 整体原理框图

2.1 最小系统的设计

单片机最小系统的三要素就是电源、晶振和复位电路。

本设计中选用的STC89C52RC需要5V的供电系统,将供电电路接在STC89C52RC的40和20引脚的位置上,40引脚接+5V,即VCC。20引脚接GND,即电源负极。

晶振为单片机系统提供基准时钟信号。STC89C52RC的18引脚和19引脚接一个11.0592MHz的晶振,外加两个20pF的电容,电容用于帮助晶振起振,并维持晶振信号的稳定。

单片机复位分为三种情况:上电复位、手动复位和程序自动复位。

上电复位即单片机上电后,单片机进行一个内部的初始化过程,保证单片机每次都从一个固定的相同的状态开始工作。手动复位即人主动去按下复位按键,让程序重新初始化重新运行。程序自动复位即单片机遇到某些情况自动复位到初始化的状态。

具体电路设计参见下图2 :


图2 单片机最小系统


2.2PCF8591电路设计


图3 PCF8591电路

其中引脚1、2、3、4是4路模拟输入,引脚5、6、7是I2C总线的硬件地址,8 脚是数 字地 GND,9 脚和 10 脚是I2C总线的 SDA 和SCL。12脚是时钟选择引脚,如果接高电平表 示用外部时钟输入,接低电平则用内部时钟,我们本次设计电路用的是内部时钟,因此12脚直接接 GND,同时 11脚悬空。13脚是模拟地 AGND。14脚是基准源,15脚是 DAC 的模拟输出,16脚是供电电源 VCC。

在软件编程过程中单片机对PCF8591进行初始化,一共发送三个字节即可。第一个字节,和 EEPROM 类似,是器件地址字节,其中7位代表地址,1位代表读写方向。地址高4位固定是0b1001,低三位是A2,A1,A0, 这三位我们电路上都接了GND,因此也就是0b000。

图 4 PCF8591 地址字节
发送到 PCF8591 的第二个字节将被存储在控制寄存器,用于控制 PCF8591 的功能。
图 5  PCF8591 控制字节
控制字节的第6位是DA使能位,这一位置1表示DA输出引脚使能,会产生模拟电压输出功能。
2.3矩阵按键电路的设计

通过高四位全部输出低电平,低四位输出高电平。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,从而能够确定是哪一个按键按下了。电路如图6示:



图6 矩阵键盘电路


3系统软件设计流程图
3.1主程序工作流程

首先开启总中断,让中断程序能够正常运行,配置T0定时1ms,初始化波形和频率,进入循环不断扫描按键动态在中断中完成按键扫描并消抖,主程序调用按键动作函数。当检测到键4按下第一次,显示三角波;当检测键4按下第二次,显示锯齿波;当检测到键4按下第三次,显示方波;当检测到键4按下第四次,显示梯形波若无检测到键按下,则输出默认正弦波;当检测到按下键8,调整波形频率。主程序流程图如图7所示:   


                             图7 主程序流程图
3.2中断子程序设计
3.2.1 T0定时器

中断子程序中,通过定时器T0执行矩阵按键扫描函数检测是否按下按键,定时器中断流程图如图8所示:


                          


图8 T0中断子程序流程图

3.2.2 T1定时器
通过定时器T1执行波形输出和频率转换,改变定时器T1的时钟周期来改变输出频率。定时器中断流程图如图9所示:


图9 T1中断子程序流程图

附录一:总电路设计图

单片机源程序如下:
  1. #include <reg52.h>
  2. unsigned char  code SinWave[256] ={           //正弦波
  3. 127 ,        133 ,        139 ,        146 ,        152 ,        158 ,        164 ,        170,
  4. 176,         181 ,        187 ,        192 ,        198 ,        203 ,        208,         212 ,
  5. 217 ,        221 ,        225 ,        229 ,        233,         236,         239,         242 ,        
  6. 244 ,        247 ,        249 ,        250 ,        252 ,        253 ,        253 ,        254 ,

  7. 254 ,        254 ,        253 ,        253,         252 ,        250 ,        249 ,        247 ,
  8. 244,         242 ,        239,         236 ,        233 ,        229 ,        225 ,        221 ,
  9. 217 ,        212 ,        208 ,        203 ,        198 ,        192 ,        187 ,        181 ,
  10. 176 ,        170 ,        164 ,        158 ,        152 ,        146 ,        139 ,        133 ,
  11.         
  12. 127 ,        121 ,        115 ,        108 ,        102 ,        96         ,   90          ,  84         ,
  13. 78         ,        73         ,        67         ,        62         ,        56        ,         51         ,        46         ,        42        ,
  14. 37         ,        33,                 29         ,        25        ,         21        ,         18         ,        15         ,        12         ,        
  15. 10         ,        7 ,                5         ,        4         ,        2         ,        1         ,        1         ,        0          ,

  16. 0         ,        0 ,                1         ,        1         ,        2         ,        4         ,        5         ,        7          ,
  17. 10         ,        12 ,        15         ,        18         ,        21         ,        25         ,        29         ,        33  ,
  18. 37         ,        42 ,        46         ,        51         ,        56         ,        62         ,        67         ,        73         ,
  19. 78         ,        84         ,        90         ,        96         ,        102 ,        108 ,        115 ,        121         ,

  20. } ;
  21. unsigned char code SawWave[256] = {        //锯齿波
  22. 0,        2,        4,        6,        8,        10,        12,        14,
  23. 16,        18,        20,        22,        24,        26,        28,        30,        
  24. 32,        34,        36,        38,        40,        42,        44,        46,        
  25. 48,        50,        52,        54,        56,        58,        60,        62,
  26.         
  27. 64,        66,        68,        70,        72,        74,        76,        78,        
  28. 80,        82,        84,        86,        88,        90,        92,        94,        
  29. 96,        98,        100,102,104,106,108,110,        
  30. 112,114,116,118,120,122,124,126,        

  31. 128        ,130,132,134,136,138,140,142,        
  32. 144        ,146,148,150,152,154,156,158,        
  33. 160        ,162,164,166,168,170,172,174,        
  34. 176        ,178,180,182,184,186,188,190,        

  35. 192,194        ,196,198,200,202,204,206,        
  36. 208,210        ,212,214,216,218,220,222,        
  37. 224,226        ,228,230,232,234,236,238,        
  38. 240,242        ,244,246,248,250,252,254,        
  39. };
  40. unsigned char code TriWave[256]= {         //三角波
  41. 0 ,    4    , 8,    12  ,  16   , 20  ,  24  ,  28 ,  
  42. 32 ,   36   , 40,    44 ,   48  ,  52 ,   56  ,  60        ,
  43. 64  ,  68   , 72 ,   76  ,  80   , 84  ,  88  ,  92  ,  
  44. 96   ,100  , 104 ,  108  , 112  , 116  , 120  , 124         ,
  45. 128  ,132  , 136,   140  , 144  , 148 ,  152  , 156 ,  
  46. 160  , 164  , 168,   172 ,  176 ,  180,   184 ,  188 ,
  47. 192  , 196 ,  200,   204,   208 ,  212 ,  216 ,  220 ,  
  48. 224  , 228 ,  232,   236 ,  240  , 244 ,  248 ,  252  ,
  49. 255  , 251 ,  247 ,  243,   239  , 235 ,  231 ,  227  ,
  50. 223  , 219 ,  215,   211 ,  207  , 203 ,  199 ,  195 ,
  51. 191  , 187 ,  183,   179,   175  , 171 ,  167 ,  163 ,
  52. 159  , 155 ,  151,   147,   143  , 139 ,  135  , 131  ,
  53. 127  , 123 ,  119,   115,   111  ,107  , 103  ,  99   ,
  54. 95   , 91  ,  87 ,   83 ,   79   , 75 ,   71  ,  67           ,
  55. 63   , 59 ,   55 ,   51 ,   47   ,43   , 39   , 35    ,
  56. 31   , 27,    23 ,   19 ,   15   , 11 ,    7   ,  3          ,
  57. };
  58. unsigned char code SquWave[256] = {        //方波
  59. 255,255,255,255,255,255,255,255,
  60. 255,255,255,255,255,255,255,255,
  61. 255,255,255,255,255,255,255,255,
  62. 255,255,255,255,255,255,255,255,

  63. 255,255,255,255,255,255,255,255,
  64. 255,255,255,255,255,255,255,255,
  65. 255,255,255,255,255,255,255,255,
  66. 255,255,255,255,255,255,255,255,
  67. };
  68. unsigned char code TraWave[256] = {//梯形波
  69. 0    , 6   ,  12 ,   18 ,   24 ,   30 ,   36  ,  42  ,  
  70. 48  ,  54   , 60 ,   66 ,   72 ,   78  ,  84  ,  90         ,
  71. 96  ,  102  , 108,   114 ,  120,   126 ,  132 ,  138 ,  
  72. 144 ,  150 ,  156,   162 ,  168 ,  174 ,  180 ,  186 ,
  73. 192 ,  198  , 204 ,  210  , 216 ,  222 ,  228 ,  234 ,  
  74. 240 ,  246 ,  252 ,  255,   255,   255,   255,   255,
  75. 255,   255,   255,   255,   255,   255,          255,   255,   
  76. 255,   255,   255,   255,   255,   255,   255,   255,
  77. 255,   255,   255,   255,   255,   255  , 249  , 243 ,  
  78. 237 ,  231  , 225  , 219  , 213,   207 ,  201  , 195  ,
  79. 189 ,  183  , 177 ,  171  , 165        ,  159  , 153  , 147 ,  
  80. 141,   135  , 129 ,  123 ,  117  , 111 ,  105  , 99 ,  
  81. 93 ,   87   , 81 ,   75  ,  69        ,  63  ,  57   , 51 ,   
  82. 45 ,   39    ,33   , 27 ,   21,    15  ,  9    , 3 ,
  83. };
  84. unsigned char code *pWave;  //波表指针
  85. unsigned char T0RH = 0;  //T0重载值的高字节
  86. unsigned char T0RL = 0;  //T0重载值的低字节
  87. unsigned char T1RH = 1;  //T1重载值的高字节
  88. unsigned char T1RL = 1;  //T1重载值的低字节
  89. unsigned char t;//函数周期
  90. unsigned char f;//频率

  91. void ConfigTimer0(unsigned int ms);
  92. void SetWaveFreq(unsigned char freq);
  93. extern void KeyScan();
  94. extern void KeyDriver();
  95. extern void I2CStart();
  96. extern void I2CStop();
  97. extern bit I2CWrite(unsigned char dat);

  98. void main()
  99. {   
  100.     EA = 1;             //开总中断
  101.     ConfigTimer0(100);  //配置T0定时1ms
  102.     pWave = SinWave;  //默认正弦波
  103.     SetWaveFreq(5);  //默认频率100Hz
  104.         f = 128;
  105.    
  106.     while (1)
  107.     {
  108.                KeyDriver();  //调用按键驱动
  109.     }
  110. }

  111. /*改变波形*/
  112. void KeyAction(unsigned char keycode)
  113. {        
  114.         static unsigned char i = 0;

  115.         if(keycode == 0x26)
  116.         {
  117.                 if(i==0)
  118.                 {
  119.                         i = 1;
  120.                         pWave = TriWave;
  121.                 }
  122.                 else if(i==1)
  123.                 {
  124.                         i = 2;
  125.                         pWave = SawWave;
  126.                 }
  127.                 else if(i==2)
  128.                 {
  129.                         i = 3;
  130.                         pWave = SquWave;
  131.                 }
  132.                 else if(i==3)
  133.                 {
  134.                         i = 4;
  135.                         pWave = TraWave;
  136.                 }
  137.                 else
  138.                 {
  139.                         i = 0;
  140.                         pWave = SinWave;
  141.                 }
  142.         }
  143. }
  144. /*改变频率*/
  145. void KeyAction_f(unsigned char keycode)
  146. {
  147.         static unsigned char i = 0;

  148.         if(keycode == 0x25)
  149.         {
  150.                 if(i==0)
  151.                 {
  152.                         i = 1;
  153.                         f = 128;
  154.                 }
  155.                 else
  156.                 {
  157.                         i = 0;
  158.                         f = 64;
  159.                 }
  160.         }        
  161. }

  162. /* 设置DAC输出值,val-设定值 */
  163. void SetDACOut(unsigned char val)
  164. {
  165.     I2CStart();
  166.     if (!I2CWrite(0x48<<1)) //寻址PCF8591,如未应答,则停止操作并返回
  167.     {
  168.         I2CStop();
  169.         return;
  170.     }
  171.     I2CWrite(0x40);         //写入控制字节
  172.     I2CWrite(val);          //写入DA值  
  173.     I2CStop();
  174. }

  175. /*改变频率*/
  176. void SetWaveFreq(unsigned char freq)
  177. {
  178.         unsigned long tmp;

  179.         tmp = (11059200/12)/(freq * 128);
  180.         tmp = 65536 - tmp;
  181.         tmp = tmp + 33;
  182.         T1RH = (unsigned char)(tmp >> 8);
  183.         T1RL = (unsigned char)tmp;
  184.         TMOD &= 0x0F;
  185.         TMOD |= 0X10;
  186.         TH1 = T1RH;
  187.         TL1 = T1RL;
  188.         ET1 = 1;
  189.         PT1 = 1;
  190.         TR1 = 1;
  191. }
  192. /* 配置并启动T0,ms-T0定时时间 */
  193. void ConfigTimer0(unsigned int ms)
  194. {
  195.     unsigned long tmp;  //临时变量
  196.    
  197.     tmp = 11059200 / 12;       //定时器计数频率
  198.     tmp = (tmp * ms) / 1000;  //计算所需的计数值
  199.     tmp = 65536 - tmp;         //计算定时器重载值
  200.     tmp = tmp + 28;            //补偿中断响应延时造成的误差
  201.     T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节
  202.     T0RL = (unsigned char)tmp;
  203.     TMOD &= 0xF0;   //清零T0的控制位
  204.     TMOD |= 0x01;   //配置T0为模式1
  205.     TH0 = T0RH;     //加载T0重载值
  206.     TL0 = T0RL;
  207.     ET0 = 1;        //使能T0中断
  208.     TR0 = 1;        //启动T0
  209. }
  210. /* T0中断服务函数,执行按键扫描 */
  211. void InterruptTimer0() interrupt 1
  212. {
  213.     TH0 = T0RH;  //重新加载重载值
  214.     TL0 = T0RL;
  215.     KeyScan();   //按键扫描        
  216.         
  217. }
  218. /* T1中断服务函数,执行波形输出 */
  219. void InterruptTimer1() interrupt 3
  220. {
  221.     static unsigned char i = 0;
  222.    
  223.     TH1 = T1RH;  //重新加载重载值
  224.     TL1 = T1RL;
  225.     //循环输出波表中的数据
  226.     SetDACOut(pWave[i]);

  227.         if(f == 128)
  228.         {
  229.             i++;
  230.             if (i >= 128)
  231.             {
  232.                 i = 0;
  233.             }
  234.         }

  235.         if(f == 64)
  236.         {
  237.             i = i+2;
  238.             if (i >= 128)
  239.             {
  240.                 i = 0;
  241.             }
  242.         }
  243. }
复制代码

新建文件1.png (41.33 KB, 下载次数: 61)

正弦波

正弦波

新建文件2.png (40.8 KB, 下载次数: 55)

三角波

三角波

新建文件3.png (39.53 KB, 下载次数: 54)

锯齿波

锯齿波

新建文件4.png (35.7 KB, 下载次数: 58)

方波

方波

新建文件5.png (41.31 KB, 下载次数: 56)

梯形波

梯形波

51hei.png (4.13 KB, 下载次数: 56)

51hei.png

波形发生器.rar

1.24 MB, 下载次数: 243, 下载积分: 黑币 -5

评分

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

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏7 分享淘帖 顶 踩1
回复

使用道具 举报

沙发
ID:604918 发表于 2022-4-28 15:05 | 只看该作者
这是用啥仿真的
回复

使用道具 举报

板凳
ID:903830 发表于 2022-11-14 16:45 | 只看该作者
请问如何实现峰峰值0-3V的锯齿波
回复

使用道具 举报

地板
ID:433219 发表于 2022-11-15 10:38 | 只看该作者
PCF8591   这死贵的价格,还不如用stc去做。大不了2片
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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