单片机
返回首页

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

2020-08-24 来源:51hei

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

单片机源程序如下:

Note:

        2020-05-06 Update

        1. Fix an error in main funciton, cause the EC11 Encoder rotate disorder.

        2. Fix an error of interface display during switch frequency.


        2020-05-24 Update

        1. Fix precision of PWM frequency

        2. Fix the information error in interface

        

        波形发生器

        作者:老刘爱捣鼓

        版本:V0.3.1

        单片机型号:STC15W4K32S4 @24MHz

        B站视频教程:https://www.bilibili.com/video/BV12k4y197Qu

        老刘爱捣鼓(全网同名)期待您的关注!


        规格:

        输出:单通道

        方波:1Hz~4MHz

        正弦波:1Hz-10kHz

        波幅:约等于VCC,5V左右

        带载能力:无带载能力

        显示屏:LCD1602

        控制:EC11编码器


        界面:

        左下角显示波形图标(方波/正弦波)和输出状态(On/OFF)

        F:频率

        D:方波占空比

        CD:时钟分频系数(For information only)

        P:用于生成正弦波的PWM频率(For information only)

        Pt:用于生成正弦波的点数(For information only)


        操作:

        单击编码器:方波界面下,切换频率和占空比

        双击编码器:开启或关闭波形输出

        长按编码器:切换方波界面/正弦波界面/电压显示界面

        旋转编码器:调节参数


        2020-05-06 更新

        1. 修正main函数循环中会引起编码器旋转混乱的错误

           将main函数中while循环中的Update_Flag=0;放到前面清零,放在后面会在编码器高速旋转时,多次触发中断而Update_Flag在最后被清零则无法正确更新LCD

        2. 修正在切换频率时,界面的显示错误


        2020-05-24 Update

        1. 修正PWM频率精度

        2. 修正界面信息的显示错误

*/


#include

#include

#include 'lcd1602.h'

#include 'wave.h'

#include 'settings.h'

#include 'delay.h'

#include 'config_stc.h'

//#include 'uart.h'

//#include 'stdio.h'


#ifndef uint8

#define uint8 unsigned char

#endif


#ifndef int8

#define int8 char

#endif


#ifndef uint16

#define uint16 unsigned int

#endif


#ifndef uint32

#define uint32 unsigned long int

#endif


#define TIMER_0 1 //定时器0中断序号

#define INT_1 2          //编码器旋转 触发外部中断

#define INT_0 0          //编码器按下 触发外部中断


uint8 Timer0_Count;

bit Update_Flag = 1;


void main(void)

{

        //LCD Pin

        P1M1 &= 0x00; //设置P1口为准双向

        P1M0 &= 0x00; //设置P1口为准双向

        P0M1 &= 0x00; //设置P0口为准双向

        P0M0 &= 0x00; //设置P0口为准双向


        //信号输出Pin

        PWM3 = 0;           //设置PWM3 P4.5低电平

        PWM4 = 0;           //设置PWM4 P4.4低电平

        P4M1 |= 0x30;  //设置P4.4(PWM4_2),4.5(PWM3_2)为高阻

        P4M0 &= ~0x30; //设置P4.4(PWM4_2),4.5(PWM3_2)为高阻


        /* 编码器旋转中断

           Interrupt for Encoder Rotation */

        IT1 = 0; //外部中断1触发方式,上升沿和下降沿

        PX1 = 1; //外部中断1高优先级

        EX1 = 1; //开启外部中断1


        /* 编码器按键中断

           Interrupt for Encoder Click */

        IT0 = 1; //外部中断0触发方式,下降沿

        PX0 = 1; //外部中断0高优先级

        EX0 = 1; //开启外部中断0


        /* 定时器0,用于更新电压信息计时

           Timer 0 for updating the information of VCC*/

        TMOD &= 0xF0;  //设置定时器0模式 16位自动重载,在Keil中debug的话,请注意,这种设置是8051的旧13位模式

        AUXR &= ~0x80; //定时器0时钟12T模式

        TL0 = 0xC0;           //设置定时初值 24MHz 20ms

        TH0 = 0x63;           //设置定时初值 24MHz 20ms

        ET0 = 1;           //允许T0溢出中断


        /* 定时器1,用于生成小于50Hz的PWM

           Timer 1 for generate the PWM when frequency less than 50Hz*/

        TMOD &= 0x0F;  //工作模式,0: 16位自动重装

        AUXR &= ~0x40; //12T

        ET1 = 1;           //允许中断


        EA = 1; //开总中断


        //UartInit();

        //UartInit_interrupt();

        PWM_Hz_Pre = PWM_Hz;

        Wave_Shape_Pre = Wave_Shape;

        Get_PWM_Duty_Limit();

        if (PWM_Duty > PWM_Max_Duty)

                PWM_Duty = PWM_Max_Duty;

        else if (PWM_Duty < PWM_Min_Duty)

                PWM_Duty = PWM_Min_Duty;

        Lcd_Init();

        while (1)

        {

                if (Update_Flag)

                {

                        /*        Update_Flag要马上清零,如果放在Update_LCD后面,会造成假如Update_LCD的过程中再次触发编码器旋转中断的话,

                                在执行完Update_LCD后,在中断中置位的Update_Flag却被清零了,造成LCD没刷新,输出和显示的不一致。

                                另一种方法是在执行Update_LCD前把中断关掉,执行完再打开中断, 但如果这里面的函数执行时间比较长,会产生旋转触发不及时,使用感受卡顿。

                                关中断来避免重复触发是有好处的,可以避免在函数执行过程中多次触发将参数修改掉,

                                函数执行过程中参数被修改,可能会造成计算结果混乱,严重时会造成溢出,甚至单片机复位死机。        */

                        Update_Flag = 0;

                        Wave_OFF();

                        if (Wave_Shape_Pre != Wave_Shape)

                        {

                                Wave_Shape_Pre = Wave_Shape;

                                if (Wave_Shape == 0)

                                {

                                        EX1 = 0; //关闭外部中断1(编码器旋转)

                                        TF0 = 0; //清除TF0标志

                                        TR0 = 1; //定时器0开始计时 (定时器0为VCC更新计时)

                                }

                                else if (Wave_Shape == 1)

                                {

                                        PWM_Hz = PWM_Hz_Pre;

                                        EX1 = 1; //开启外部中断1(编码器旋转)

                                        TR0 = 0; //关闭定时器0 (定时器0为VCC更新计时)

                                        TF0 = 0; //清除TF0标志

                                }


                                else if (Wave_Shape == 2)

                                {

                                        PWM_Hz_Pre = PWM_Hz;

                                }

                        }

                        if (Wave_Shape == 1) //方波

                        {

                                Set_PWMCKS_PS();

                                Set_PWM_Cycle();

                                Set_PWM_Width();

                        }

                        else if (Wave_Shape == 2) //正弦波

                        {

                                Set_Sin_Table_Times();

                                Set_PWMCKS_PS();

                                Set_PWM_Cycle();

                        }


                        Update_LCD();

                        //EX1 = 0;

                        Set_Wave_Shape();


                        //IE1=0;

                        //EX1 = 1;

                }

        }

}


/* 编码器旋转响应函数

   Encoder Rotate */

void Scan_EC11(void)

{

        /* 正转

           Rotate clockwise */

        if ((EC11_A != EC11_B))

        {


                Change_Val(1);

        }

        /* 反转

           Rotate anticlockwise*/

        else if ((EC11_A == EC11_B))

        {

                Change_Val(0);

        }

}


/* 编码器旋转中断

   Interrupt for Encoder rotation */

void INT1_interrupt(void) interrupt INT_1

{

        Delay1ms();

        Scan_EC11();

        Update_Flag = 1;

        //Delay50ms();

        IE1 = 0;

}


/* 编码器点击中断

   Interrupt for Encoder click */

void INT0_interrupt(void) interrupt INT_0

{

        Delay5ms();

        if (!EC11_KEY)

        {

                /* 长按

                   Long Press */

                if (Delay500ms_long_click())

                {

                        Wave_Shape++;

                        if (Wave_Shape > WAVE_NUM)

                                Wave_Shape = 0;

                        if (Wave_Shape == 2)

                                Options = 1;

                        WAVE_ON = 0;

                        Clear_LCD_Flag = 1;

                }

                /* 双击

                   Double click */

                else if (Delay200ms_double_click())

                {

                        if (Wave_Shape > 0)

                        {

                                WAVE_ON = ~WAVE_ON;

                        }

                }

                /* 单击

                   Single click */

                else

                {

                        if (Wave_Shape == 1)

                                Options = ~Options;

                }

                Update_Flag = 1;

        }

        Delay5ms();

        IE0 = 0;

}


/* 更新电压信息计时中断

   Timer interrupt for update voltage information */

void TIMER0_interrupt() interrupt TIMER_0

{

        if (++Timer0_Count > 200) //200x20=4000ms

        {

                Timer0_Count = 0;

                Update_Flag = 1;

        }

}


进入单片机查看更多内容>>
相关视频
精选电路图
  • 单稳态控制电路设计与分析

  • 永不缺相启动运行的电动机控制电路

  • MT3608构成3.7V转12V的升压电路图

  • 运算放大器IC741的基本工作原理及在电路中的实现方式

  • 比较常见的功率整流器和滤波电路

  • 基于CA3193的热电偶放大器电路

    相关电子头条文章