找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机控制信号发生器源程序(正弦波、方波)Gerber文件

[复制链接]
跳转到指定楼层
楼主
信号发生器,有Keil程序和Gerber打板。

单片机型号:STC15W4K32S4
数字编码器EC11作为控制波形、频率、占空比的开关
液晶1602A作为显示信息


Gerber文件下载(无PCB): 51单片机信号发生器机.7z (3.33 MB, 下载次数: 63)

单片机源程序如下:
  1. Note:
  2.         2020-05-06 Update
  3.         1. Fix an error in main funciton, cause the EC11 Encoder rotate disorder.
  4.         2. Fix an error of interface display during switch frequency.

  5.         2020-05-24 Update
  6.         1. Fix precision of PWM frequency
  7.         2. Fix the information error in interface
  8.         
  9.         波形发生器
  10.         作者:老刘爱捣鼓
  11.         版本:V0.3.1
  12.         单片机型号:STC15W4K32S4 @24MHz
  13.         B站视频教程:https://www.bilibili.com/video/BV12k4y197Qu
  14.         老刘爱捣鼓(全网同名)期待您的关注!

  15.         规格:
  16.         输出:单通道
  17.         方波:1Hz~4MHz
  18.         正弦波:1Hz-10kHz
  19.         波幅:约等于VCC,5V左右
  20.         带载能力:无带载能力
  21.         显示屏:LCD1602
  22.         控制:EC11编码器

  23.         界面:
  24.         左下角显示波形图标(方波/正弦波)和输出状态(On/OFF)
  25.         F:频率
  26.         D:方波占空比
  27.         CD:时钟分频系数(For information only)
  28.         P:用于生成正弦波的PWM频率(For information only)
  29.         Pt:用于生成正弦波的点数(For information only)

  30.         操作:
  31.         单击编码器:方波界面下,切换频率和占空比
  32.         双击编码器:开启或关闭波形输出
  33.         长按编码器:切换方波界面/正弦波界面/电压显示界面
  34.         旋转编码器:调节参数

  35.         2020-05-06 更新
  36.         1. 修正main函数循环中会引起编码器旋转混乱的错误
  37.            将main函数中while循环中的Update_Flag=0;放到前面清零,放在后面会在编码器高速旋转时,多次触发中断而Update_Flag在最后被清零则无法正确更新LCD
  38.         2. 修正在切换频率时,界面的显示错误

  39.         2020-05-24 Update
  40.         1. 修正PWM频率精度
  41.         2. 修正界面信息的显示错误
  42. */

  43. #include <reg51.h>
  44. #include <intrins.h>
  45. #include "lcd1602.h"
  46. #include "wave.h"
  47. #include "settings.h"
  48. #include "delay.h"
  49. #include "config_stc.h"
  50. //#include "uart.h"
  51. //#include "stdio.h"

  52. #ifndef uint8
  53. #define uint8 unsigned char
  54. #endif

  55. #ifndef int8
  56. #define int8 char
  57. #endif

  58. #ifndef uint16
  59. #define uint16 unsigned int
  60. #endif

  61. #ifndef uint32
  62. #define uint32 unsigned long int
  63. #endif

  64. #define TIMER_0 1 //定时器0中断序号
  65. #define INT_1 2          //编码器旋转 触发外部中断
  66. #define INT_0 0          //编码器按下 触发外部中断

  67. uint8 Timer0_Count;
  68. bit Update_Flag = 1;

  69. void main(void)
  70. {
  71.         //LCD Pin
  72.         P1M1 &= 0x00; //设置P1口为准双向
  73.         P1M0 &= 0x00; //设置P1口为准双向
  74.         P0M1 &= 0x00; //设置P0口为准双向
  75.         P0M0 &= 0x00; //设置P0口为准双向

  76.         //信号输出Pin
  77.         PWM3 = 0;           //设置PWM3 P4.5低电平
  78.         PWM4 = 0;           //设置PWM4 P4.4低电平
  79.         P4M1 |= 0x30;  //设置P4.4(PWM4_2),4.5(PWM3_2)为高阻
  80.         P4M0 &= ~0x30; //设置P4.4(PWM4_2),4.5(PWM3_2)为高阻

  81.         /* 编码器旋转中断
  82.            Interrupt for Encoder Rotation */
  83.         IT1 = 0; //外部中断1触发方式,上升沿和下降沿
  84.         PX1 = 1; //外部中断1高优先级
  85.         EX1 = 1; //开启外部中断1

  86.         /* 编码器按键中断
  87.            Interrupt for Encoder Click */
  88.         IT0 = 1; //外部中断0触发方式,下降沿
  89.         PX0 = 1; //外部中断0高优先级
  90.         EX0 = 1; //开启外部中断0

  91.         /* 定时器0,用于更新电压信息计时
  92.            Timer 0 for updating the information of VCC*/
  93.         TMOD &= 0xF0;  //设置定时器0模式 16位自动重载,在Keil中debug的话,请注意,这种设置是8051的旧13位模式
  94.         AUXR &= ~0x80; //定时器0时钟12T模式
  95.         TL0 = 0xC0;           //设置定时初值 24MHz 20ms
  96.         TH0 = 0x63;           //设置定时初值 24MHz 20ms
  97.         ET0 = 1;           //允许T0溢出中断

  98.         /* 定时器1,用于生成小于50Hz的PWM
  99.            Timer 1 for generate the PWM when frequency less than 50Hz*/
  100.         TMOD &= 0x0F;  //工作模式,0: 16位自动重装
  101.         AUXR &= ~0x40; //12T
  102.         ET1 = 1;           //允许中断

  103.         EA = 1; //开总中断

  104.         //UartInit();
  105.         //UartInit_interrupt();
  106.         PWM_Hz_Pre = PWM_Hz;
  107.         Wave_Shape_Pre = Wave_Shape;
  108.         Get_PWM_Duty_Limit();
  109.         if (PWM_Duty > PWM_Max_Duty)
  110.                 PWM_Duty = PWM_Max_Duty;
  111.         else if (PWM_Duty < PWM_Min_Duty)
  112.                 PWM_Duty = PWM_Min_Duty;
  113.         Lcd_Init();
  114.         while (1)
  115.         {
  116.                 if (Update_Flag)
  117.                 {
  118.                         /*        Update_Flag要马上清零,如果放在Update_LCD后面,会造成假如Update_LCD的过程中再次触发编码器旋转中断的话,
  119.                                 在执行完Update_LCD后,在中断中置位的Update_Flag却被清零了,造成LCD没刷新,输出和显示的不一致。
  120.                                 另一种方法是在执行Update_LCD前把中断关掉,执行完再打开中断, 但如果这里面的函数执行时间比较长,会产生旋转触发不及时,使用感受卡顿。
  121.                                 关中断来避免重复触发是有好处的,可以避免在函数执行过程中多次触发将参数修改掉,
  122.                                 函数执行过程中参数被修改,可能会造成计算结果混乱,严重时会造成溢出,甚至单片机复位死机。        */
  123.                         Update_Flag = 0;
  124.                         Wave_OFF();
  125.                         if (Wave_Shape_Pre != Wave_Shape)
  126.                         {
  127.                                 Wave_Shape_Pre = Wave_Shape;
  128.                                 if (Wave_Shape == 0)
  129.                                 {
  130.                                         EX1 = 0; //关闭外部中断1(编码器旋转)
  131.                                         TF0 = 0; //清除TF0标志
  132.                                         TR0 = 1; //定时器0开始计时 (定时器0为VCC更新计时)
  133.                                 }
  134.                                 else if (Wave_Shape == 1)
  135.                                 {
  136.                                         PWM_Hz = PWM_Hz_Pre;
  137.                                         EX1 = 1; //开启外部中断1(编码器旋转)
  138.                                         TR0 = 0; //关闭定时器0 (定时器0为VCC更新计时)
  139.                                         TF0 = 0; //清除TF0标志
  140.                                 }

  141.                                 else if (Wave_Shape == 2)
  142.                                 {
  143.                                         PWM_Hz_Pre = PWM_Hz;
  144.                                 }
  145.                         }
  146.                         if (Wave_Shape == 1) //方波
  147.                         {
  148.                                 Set_PWMCKS_PS();
  149.                                 Set_PWM_Cycle();
  150.                                 Set_PWM_Width();
  151.                         }
  152.                         else if (Wave_Shape == 2) //正弦波
  153.                         {
  154.                                 Set_Sin_Table_Times();
  155.                                 Set_PWMCKS_PS();
  156.                                 Set_PWM_Cycle();
  157.                         }

  158.                         Update_LCD();
  159.                         //EX1 = 0;
  160.                         Set_Wave_Shape();

  161.                         //IE1=0;
  162.                         //EX1 = 1;
  163.                 }
  164.         }
  165. }

  166. /* 编码器旋转响应函数
  167.    Encoder Rotate */
  168. void Scan_EC11(void)
  169. {
  170.         /* 正转
  171.            Rotate clockwise */
  172.         if ((EC11_A != EC11_B))
  173.         {

  174.                 Change_Val(1);
  175.         }
  176.         /* 反转
  177.            Rotate anticlockwise*/
  178.         else if ((EC11_A == EC11_B))
  179.         {
  180.                 Change_Val(0);
  181.         }
  182. }

  183. /* 编码器旋转中断
  184.    Interrupt for Encoder rotation */
  185. void INT1_interrupt(void) interrupt INT_1
  186. {
  187.         Delay1ms();
  188.         Scan_EC11();
  189.         Update_Flag = 1;
  190.         //Delay50ms();
  191.         IE1 = 0;
  192. }

  193. /* 编码器点击中断
  194.    Interrupt for Encoder click */
  195. void INT0_interrupt(void) interrupt INT_0
  196. {
  197.         Delay5ms();
  198.         if (!EC11_KEY)
  199.         {
  200.                 /* 长按
  201.                    Long Press */
  202.                 if (Delay500ms_long_click())
  203.                 {
  204.                         Wave_Shape++;
  205.                         if (Wave_Shape > WAVE_NUM)
  206.                                 Wave_Shape = 0;
  207.                         if (Wave_Shape == 2)
  208.                                 Options = 1;
  209.                         WAVE_ON = 0;
  210.                         Clear_LCD_Flag = 1;
  211.                 }
  212.                 /* 双击
  213.                    Double click */
  214.                 else if (Delay200ms_double_click())
  215.                 {
  216.                         if (Wave_Shape > 0)
  217.                         {
  218.                                 WAVE_ON = ~WAVE_ON;
  219.                         }
  220.                 }
  221.                 /* 单击
  222.                    Single click */
  223.                 else
  224.                 {
  225.                         if (Wave_Shape == 1)
  226.                                 Options = ~Options;
  227.                 }
  228.                 Update_Flag = 1;
  229.         }
  230.         Delay5ms();
  231.         IE0 = 0;
  232. }

  233. /* 更新电压信息计时中断
  234.    Timer interrupt for update voltage information */
  235. void TIMER0_interrupt() interrupt TIMER_0
  236. {
  237.         if (++Timer0_Count > 200) //200x20=4000ms
  238.         {
  239.                 Timer0_Count = 0;
  240.                 Update_Flag = 1;
  241.         }
  242. }

复制代码

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:813018 发表于 2020-8-20 19:44 | 只看该作者
有沒有hen編程源碼
回复

使用道具 举报

板凳
ID:759755 发表于 2020-12-25 09:21 | 只看该作者
有配套原理图吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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