• 【波形/信号发生器】基于 STC1524K32S4 for C on Keil


    本项目是B站UP主老刘爱鼓捣制作的波形信号发生器:如何用单片机自制波形发生器生成方波和正弦波

    项目GitHbu地址:https://github.com/CreativeLau/Function_Generator_STC

    项目预览:

    来自老刘爱鼓捣的GitHub仓库

     项目分析:

    • 无负电源,输出无负值波形
    • 无带负载能力

    突然习惯了 STM32 ,再看寄存器操作的C还有些不太习惯呢


    原理图

    输出端口部分

    SIN、PWM 分别为正弦,方波输出端口。

    滤波呗?

    控制部分

    现在发现 EC11 真是个好东西。


    程序分析

    包含函数:

    名称功能
    main主程序
    adc_stc15.c检测电压的程序
    lcd1602基本上就是一些LCD1602的点亮配置函数库
    settingsLCD的显示、波形频率的改变控制
    delay延时函数、EC11长按/双击检测函数都在此文件
    wave有关输出波形的设定都在此文件

    有关 LCD1602 显示库的部分就不做过多介绍了,这个东西是直接copy就能用的。

    本项目最关心的为波形发生,故只分析波形发生之相关的函数!关于波形的改变以及LCD显示属于简单问题,在本文不予讨论。

    主程序

    1. #include
    2. #include
    3. #include "lcd1602.h"
    4. #include "wave.h"
    5. #include "settings.h"
    6. #include "delay.h"
    7. #include "config_stc.h"
    8. #ifndef uint8
    9. #define uint8 unsigned char
    10. #endif
    11. #ifndef int8
    12. #define int8 char
    13. #endif
    14. #ifndef uint16
    15. #define uint16 unsigned int
    16. #endif
    17. #ifndef uint32
    18. #define uint32 unsigned long int
    19. #endif
    20. #define TIMER_0 1 //定时器0中断序号
    21. #define INT_1 2 //编码器旋转 触发外部中断
    22. #define INT_0 0 //编码器按下 触发外部中断
    23. uint8 Timer0_Count; //时间计数器,定时器0用
    24. bit Update_Flag = 1; //更新标志位
    25. sbit SEL=P0^4; //继电器控制位
    26. void main(void)
    27. {
    28. //LCD Pin
    29. P1M1 &= 0x00; //设置P1口为准双向
    30. P1M0 &= 0x00; //设置P1口为准双向
    31. P0M1 &= 0x00; //设置P0口为准双向
    32. P0M0 &= 0x00; //设置P0口为准双向
    33. //信号输出Pin
    34. PWM3 = 0; //设置PWM3 P4.5低电平
    35. PWM4 = 0; //设置PWM4 P4.4低电平
    36. P4M1 |= 0x30; //设置P4.4(PWM4_2),4.5(PWM3_2)为高阻
    37. P4M0 &= ~0x30; //设置P4.4(PWM4_2),4.5(PWM3_2)为高阻
    38. /* 编码器旋转中断
    39. Interrupt for Encoder Rotation */
    40. IT1 = 0; //外部中断1触发方式,上升沿和下降沿
    41. PX1 = 1; //外部中断1高优先级
    42. EX1 = 1; //开启外部中断1
    43. /* 编码器按键中断
    44. Interrupt for Encoder Click */
    45. IT0 = 1; //外部中断0触发方式,下降沿
    46. PX0 = 1; //外部中断0高优先级
    47. EX0 = 1; //开启外部中断0
    48. /* 定时器0,用于更新电压信息计时
    49. Timer 0 for updating the information of VCC*/
    50. TMOD &= 0xF0; //设置定时器0模式 16位自动重载,在Keil中debug的话,请注意,这种设置是8051的旧13位模式
    51. AUXR &= ~0x80; //定时器0时钟12T模式
    52. TL0 = 0xC0; //设置定时初值 24MHz 20ms
    53. TH0 = 0x63; //设置定时初值 24MHz 20ms
    54. ET0 = 1; //允许T0溢出中断
    55. /* 定时器1,用于生成小于50Hz的PWM
    56. Timer 1 for generate the PWM when frequency less than 50Hz*/
    57. TMOD &= 0x0F; //工作模式,0: 16位自动重装
    58. AUXR &= ~0x40; //12T
    59. ET1 = 1; //允许中断
    60. EA = 1; //开总中断
    61. PWM_Hz_Pre = PWM_Hz; //PWM_Hz_Pre记录上一次PWM频率
    62. Wave_Shape_Pre = Wave_Shape; //Wave_Shape_Pre记录上次波形标志
    63. Get_PWM_Duty_Limit(); //根据PWM_Hz设定占空比上下限
    64. if (PWM_Duty > PWM_Max_Duty)
    65. PWM_Duty = PWM_Max_Duty;
    66. else if (PWM_Duty < PWM_Min_Duty)
    67. PWM_Duty = PWM_Min_Duty;
    68. Lcd_Init();
    69. while (1)
    70. {
    71. if (Update_Flag) //更新标志位
    72. {
    73. Update_Flag = 0; //清除标志位
    74. Wave_OFF(); //关闭波形输出
    75. if (Wave_Shape_Pre != Wave_Shape) //判断是否改变输出波形,1、方波;2、正弦波
    76. {
    77. Wave_Shape_Pre = Wave_Shape;
    78. if (Wave_Shape == 0) //显示电源电压
    79. {
    80. EX1 = 0; //关闭外部中断1(编码器旋转)
    81. TF0 = 0; //清除TF0标志
    82. TR0 = 1; //定时器0开始计时 (定时器0为VCC更新计时)
    83. }
    84. else if (Wave_Shape == 1) //方波输出
    85. {
    86. PWM_Hz = PWM_Hz_Pre;
    87. EX1 = 1; //开启外部中断1(编码器旋转)
    88. TR0 = 0; //关闭定时器0 (定时器0为VCC更新计时)
    89. TF0 = 0; //清除TF0标志
    90. }
    91. else if (Wave_Shape == 2) //正弦波输出
    92. {
    93. PWM_Hz_Pre = PWM_Hz;
    94. }
    95. }
    96. if (Wave_Shape == 1) //方波输出模式
    97. {
    98. SEL = 1; //继电器控制
    99. Set_PWMCKS_PS();
    100. Set_PWM_Cycle();
    101. Set_PWM_Width();
    102. }
    103. else if (Wave_Shape == 2) //正弦波输出模式
    104. {
    105. SEL = 0;//继电器控制
    106. Set_Sin_Table_Times();
    107. Set_PWMCKS_PS();
    108. Set_PWM_Cycle();
    109. }
    110. Update_LCD(); //更新LCD显示
    111. Set_Wave_Shape(); //生成正弦波SPWM中断
    112. }
    113. }
    114. }
    115. /* 编码器旋转响应函数
    116. Encoder Rotate */
    117. void Scan_EC11(void)
    118. {
    119. /* 正转
    120. Rotate clockwise */
    121. if ((EC11_A != EC11_B))
    122. {
    123. Change_Val(1);
    124. }
    125. /* 反转
    126. Rotate anticlockwise*/
    127. else if ((EC11_A == EC11_B))
    128. {
    129. Change_Val(0);
    130. }
    131. }
    132. /* 编码器旋转中断
    133. Interrupt for Encoder rotation */
    134. void INT1_interrupt(void) interrupt INT_1
    135. {
    136. Delay1ms();
    137. Scan_EC11();
    138. Update_Flag = 1; //更新标志
    139. //Delay50ms();
    140. IE1 = 0; //清除中断标志位
    141. }
    142. /* 编码器点击中断
    143. Interrupt for Encoder click */
    144. void INT0_interrupt(void) interrupt INT_0
    145. {
    146. Delay5ms();
    147. if (!EC11_KEY) //还在按下状态(EC11_KEY=0),去抖动
    148. {
    149. /* 长按
    150. Long Press */
    151. if (Delay500ms_long_click()) //长按检测函数,长按返回1
    152. {
    153. Wave_Shape++; //改变输出波形
    154. if (Wave_Shape > WAVE_NUM)
    155. Wave_Shape = 0;
    156. if (Wave_Shape == 2)
    157. Options = 1;
    158. WAVE_ON = 0; //输出波形控制标志位
    159. Clear_LCD_Flag = 1; //清屏LCD标志位
    160. }
    161. /* 双击
    162. Double click */
    163. else if (Delay200ms_double_click()) //双击检测函数,双击返回1
    164. {
    165. if (Wave_Shape > 0)
    166. {
    167. WAVE_ON = ~WAVE_ON; //改变输出波形控制标志位
    168. }
    169. }
    170. /* 单击
    171. Single click */
    172. else
    173. {
    174. if (Wave_Shape == 1) //方波输出状态下
    175. Options = ~Options; //频率、占空比切换控制标志位
    176. }
    177. Update_Flag = 1;
    178. }
    179. Delay5ms();
    180. IE0 = 0;
    181. }
    182. /* 更新电压信息计时中断
    183. Timer interrupt for update voltage information */
    184. void TIMER0_interrupt() interrupt TIMER_0
    185. {
    186. if (++Timer0_Count > 200) //200x20=4000ms
    187. {
    188. Timer0_Count = 0;
    189. Update_Flag = 1;
    190. }
    191. }

    EC11 中断口判断为 A 端口。由 A 端口的上升沿/下降沿后的电平和 B 端口的电平做对比,判断是正转还是反转。(每次用 EC11 都会把正转反转搞混,我像个废物)

    关于 EC11 我有篇文章写过,请参考(只能作为参考):多功能小键盘(基于HK32F030M)

    波形控制函数

    wave.h

    列出这些只是为了看 wave.c 文件时方便。

    1. #ifndef WAVE_H
    2. #define WAVE_H
    3. #include
    4. #include
    5. #include "config_stc.h"
    6. #include "delay.h"
    7. #ifndef uint8
    8. #define uint8 unsigned char
    9. #endif
    10. #ifndef int8
    11. #define int8 char
    12. #endif
    13. #ifndef uint16
    14. #define uint16 unsigned int
    15. #endif
    16. #ifndef uint32
    17. #define uint32 unsigned long int
    18. #endif
    19. #define FOSC 24000000UL //主时钟
    20. #define SPWM_VECTOR 22 //PWM中断序号
    21. #define TIMER_1 3 //定时器1中断序号
    22. #define CBIF 0x40 //PWM计数器归零中断标志
    23. #define SIN_TABLE_PWM_HZ 150000 //T_SinTable计算使用的PWM频率,用FOSC/SIN_TABLE_PWM_HZ求出PWM最大宽度
    24. #define SIN_POINTS 1000 //T_SinTable点数
    25. #define SIN_OFFSET 1 //SIN值偏移量,用于修正第一次翻转和第二次翻转都为0的情况,本应该翻转两次,这样只翻转了一次,造成电平反向
    26. #define WAVE_NUM 2 //波形选项的数量,暂时只做了方波和正弦波,设置为2,当Wave_Shape=0时,跳转到显示VCC电压
    27. #define PWM_MAX_DUTY 99 //PWM最大占空比
    28. #define PWM_MIN_DUTY 1 //PWM最小占空比
    29. #define PWM_MIN_WIDTH 50 //PWM最小宽度持续时间 ns
    30. #define PWM_MAX_HZ 4000000 //PWM最大频率4MHz
    31. #define PWM_MIN_HZ 1 //PWM最小频率1Hz
    32. #define SIN_MAX_HZ 10000 //SIN最大频率10kHz
    33. #define SIN_MIN_HZ 1 //SIN最小频率1Hz
    34. #define CKS_50HZ 12 //小于50Hz的时钟分频
    35. #define PWMC (*(uint16 volatile xdata *)0xfff0) //PWM计数器
    36. #define PWMCKS (*(uint8 volatile xdata *)0xfff2) //PWM时钟选择位
    37. #define PWM3T1 (*(uint16 volatile xdata *)0xff10) //PWM3T1计数器
    38. #define PWM3T2 (*(uint16 volatile xdata *)0xff12) //PWM3T2计数器
    39. #define PWM3CR (*(uint8 volatile xdata *)0xff14) //PWM3控制位
    40. #define PWM4T1 (*(uint16 volatile xdata *)0xFF20) //PWM4T1计数器
    41. #define PWM4T2 (*(uint16 volatile xdata *)0xFF22) //PWM4T2计数器
    42. #define PWM4CR (*(uint8 volatile xdata *)0xFF24) //PWM4控制位
    43. extern uint8 PWMCKS_PS; //系统时钟分频系数
    44. extern uint32 PWM_Hz; //PWM频率
    45. extern uint32 PWM_Hz_Pre; //记录上一次PWM频率
    46. extern int8 PWM_Duty; //PWM占空比
    47. extern uint32 SIN_Hz; //SIN频率
    48. extern uint8 Wave_Shape; //波形标志 1:方波 2:正弦波
    49. extern uint8 Wave_Shape_Pre; //上次波形标志
    50. extern uint8 Sin_Table_Times; //SIN倍率
    51. extern bit WAVE_ON; //输出波形标志位 1:ON 2:OFF
    52. void Set_Wave_Shape();
    53. void Wave_OFF();
    54. void Set_PWMCKS_PS();
    55. void Set_PWM_Cycle();
    56. void Set_PWM_Width();
    57. void Set_Sin_Table_Times();
    58. #endif

    wave.c

    其实作者已经弄的很好了,但我还是想着再自己分析分析!

    总的来说难度不算很高!正弦波的数据存储在 T_SineTable.h 文件中。

    1. #include "wave.h"
    2. #include "T_SineTable.h"
    3. bit WAVE_ON = 0; //输出波形标志位 1:ON 0:OFF
    4. uint8 PWMCKS_PS = 0; //系统时钟分频系数
    5. uint32 PWM_Hz = 100; //PWM频率
    6. uint32 PWM_Hz_Pre; //记录上一次PWM频率
    7. uint32 PWM_Cycle; //PWM周期(最大值为32767)
    8. int8 PWM_Duty = 50; //PWM占空比
    9. uint32 PWM_Width; //PWM高电平宽度
    10. uint32 SIN_Hz = 100; //SIN频率
    11. uint8 Wave_Shape = 1; //波形标志 1:方波 2:正弦波
    12. uint8 Wave_Shape_Pre; //上次波形标志
    13. uint16 PWM_Index = 0; //SPWM查表索引
    14. uint16 T_SinTable_Current[SIN_POINTS]; //根据原始SIN值计算新的SIN表
    15. uint8 Sin_Table_Times = 1; //SIN倍率
    16. uint32 PWM1_high, PWM1_low;
    17. uint16 n, n_high, n_low;
    18. void Set_PWMCKS_PS(void)
    19. {
    20. /* 0X7fff=32767是15位PWM计数器的最大值,
    21. * 因此FOSC / 0X7fff是主时钟不分频的情况下PWM_Hz的最小值
    22. * 24000000/32767 = 732
    23. */
    24. if (PWM_Hz <= (FOSC / 0X7fff))
    25. {
    26. PWMCKS_PS = 0x0F;
    27. }
    28. else
    29. {
    30. PWMCKS_PS = 0x00;
    31. }
    32. }
    33. /*
    34. *
    35. *
    36. */
    37. /* PWM周期,大于50Hz时使用增强型PWM波形发生器直接生成,
    38. * 适用STC15W4K和STC8,小于50Hz使用定时器控制GPIO翻转
    39. */
    40. void Set_PWM_Cycle(void)
    41. {
    42. if (PWM_Hz < 50)
    43. {
    44. PWM_Cycle = FOSC / CKS_50HZ / PWM_Hz; //使用定时器1循环生成低频方波
    45. // 主时钟 / 12分频系数 / PWM_Hz
    46. }
    47. else
    48. {
    49. PWM_Cycle = (FOSC * 10 / (PWMCKS_PS + 1) / PWM_Hz + 5) / 10 - 1; //使用STC15W4K的高精度PWM生成高频方波
    50. }
    51. }
    52. /* PWM高电平宽度 */
    53. void Set_PWM_Width(void)
    54. {
    55. PWM_Width = (PWM_Cycle * PWM_Duty * 10 + 5) / 10 / 100;
    56. }
    57. /* 设置正弦波时间表 */
    58. void Set_Sin_Table_Times()
    59. {
    60. Sin_Table_Times = 1;
    61. if (SIN_Hz > 6000)
    62. Sin_Table_Times = 100;
    63. else if (SIN_Hz > 5000)
    64. Sin_Table_Times = 50;
    65. else if (SIN_Hz > 3000)
    66. Sin_Table_Times = 40;
    67. else if (SIN_Hz > 2500)
    68. Sin_Table_Times = 25;
    69. else if (SIN_Hz > 1000)
    70. Sin_Table_Times = 20;
    71. else if (SIN_Hz > 500)
    72. Sin_Table_Times = 8;
    73. else if (SIN_Hz > 250)
    74. Sin_Table_Times = 4;
    75. else if (SIN_Hz > 100)
    76. Sin_Table_Times = 2;
    77. PWM_Hz = SIN_Hz * SIN_POINTS / Sin_Table_Times;
    78. }
    79. /* 关闭波形输出 */
    80. void Wave_OFF(void)
    81. {
    82. P_SW2 |= 0x80; //访问xSFR
    83. PWMCR &= ~0x80; //关闭PWM模块 (大于50Hz的方波和正弦波)
    84. PWMCR &= ~0x40; //禁止PWM计数器归零中断 (正弦波)
    85. PWMIF &= ~CBIF; //清除中断标志
    86. P_SW2 &= ~0x80; //恢复访问XRAM
    87. TR1 = 0; //关闭定时器1(小于50Hz的方波)
    88. TF1 = 0; //清除定时器1中断标志
    89. //PWM IO状态
    90. PWM3 = 0; //设置PWM3 P4.5低电平 方波
    91. PWM4 = 0; //设置PWM4 P4.4低电平 正弦波
    92. P4M1 |= 0x30; //设置P4.4(PWM4_2),4.5(PWM3_2)为高阻
    93. P4M0 &= ~0x30; //设置P4.4(PWM4_2),4.5(PWM3_2)为高阻
    94. }
    95. /* PWM 配置函数 */
    96. void PWM_Config(void)
    97. {
    98. if (WAVE_ON)
    99. {
    100. //PWM IO状态
    101. PWM3 = 0; //设置PWM3 P4.5低电平
    102. P4M1 &= ~0x20; //设置P4.5为推挽输出
    103. P4M0 |= 0x20; //设置P4.5为推挽输出
    104. /* 占空比为0时,始终输出低电平
    105. Output low when duty cycle is 0*/
    106. if (PWM_Width == 0)
    107. {
    108. TR1 = 0; //关闭定时器1(小于50Hz的方波)
    109. TF1 = 0; //清除定时器1中断标志
    110. PWMCR &= ~0x02; //PWM通道3的端口为GPIO
    111. PWM3 = 0; //PWM通道3始终输出低电平
    112. }
    113. /* 占空比为100%时,始终输出高电平
    114. Output high when duty cycle is 100%*/
    115. else if (PWM_Width == PWM_Cycle)
    116. {
    117. TR1 = 0; //关闭定时器1(小于50Hz的方波)
    118. TF1 = 0; //清除定时器1中断标志
    119. PWMCR &= ~0x02; //PWM通道3的端口为GPIO
    120. PWM3 = 1; //PWM通道3始终输出高电平
    121. }
    122. /* PWM频率大于等于50时,使用内置增强型PWM输出
    123. Use enhanced PWM waveform generator when PWM frequency higher than or equal to 50*/
    124. else if (PWM_Hz >= 50)
    125. {
    126. P_SW2 |= 0x80; //访问xSFR
    127. PWMCKS = 0x00; //PWM时钟选择
    128. PWMCKS |= PWMCKS_PS; //系统时钟分频作为PWM时钟
    129. PWMC = PWM_Cycle; //设置PWM周期
    130. PWMCFG &= ~0x02; //配置PWM的输出初始电平
    131. PWM3T1 = 0; //第一次翻转计数器
    132. PWM3T2 = PWM_Width; //第二次翻转计数器
    133. PWM3CR = 0x08; //PWM3输出到P4.5
    134. PWMCR = 0x02; //使能PWM3输出
    135. PWMCR &= ~0x40; //禁止PWM计数器归零中断
    136. PWMCR |= 0x80; //使能PWM模块
    137. P_SW2 &= ~0x80; //恢复访问XRAM
    138. }
    139. /* PWM频率小于50时,使用定时器输出
    140. Use timer when PWM frequency lower than 50*/
    141. else
    142. {
    143. PWMCR &= ~0x02; //PWM通道3的端口为GPIO
    144. PWM3 = 0; //PWM通道3输出低电平
    145. PWM1_high = PWM_Width; //高电平持续总时间
    146. PWM1_low = PWM_Cycle - PWM_Width; //低电平持续总时间
    147. n_high = PWM1_high / 65536; //高电平超过定时器溢出的次数
    148. n_low = PWM1_low / 65536; //低电平超过定时器溢出的次数
    149. PWM1_high = 65535 - PWM1_high % 65536 + FOSC * 2 / 10000 / CKS_50HZ; //定时器初值,并修正为判断PWM电平变化延时的200us
    150. PWM1_low = 65535 - PWM1_low % 65536 + FOSC * 2 / 10000 / CKS_50HZ; //定时器初值,并修正为判断PWM电平变化延时的200us
    151. if (PWM1_high > 65535) //修正后的定时器初值大于65535则再次修正
    152. {
    153. n_high--;
    154. PWM1_high -= 65535;
    155. }
    156. if (PWM1_low > 65535) //修正后的定时器初值大于65535则再次修正
    157. {
    158. n_low--;
    159. PWM1_low -= 65535;
    160. }
    161. n = n_low;
    162. TH1 = (uint8)(PWM1_low >> 8); //如果是输出低电平,则装载低电平时间。
    163. TL1 = (uint8)PWM1_low;
    164. TR1 = 1; //定时器1开始运行
    165. }
    166. }
    167. else
    168. {
    169. Wave_OFF();
    170. }
    171. }
    172. /* 正弦波输出配置 */
    173. void Sin_Wave_Config(void)
    174. {
    175. int i;
    176. /* SPWM_interrupt中断函数运行需要时间,
    177. * SPWM频率120K是STC15W4K32S4的上限,
    178. * 再高就来不及通过SPWM_interrupt调节占空比了
    179. */
    180. float Sin_Cycle_times;
    181. /* T_SinTable的数值是根据SIN_TABLE_PWM_HZ计算得到最大周期,
    182. * 周期为FOSC/SIN_TABLE_PWM_HZ,24MHz主时钟150kHz对应周期160
    183. * 根据当前的PWM_Hz重新计算正弦表,使得正弦波幅尽量大
    184. */
    185. Sin_Cycle_times = SIN_TABLE_PWM_HZ * 1.0 / PWM_Hz; //当前PWM_Hz相对SIN_TABLE_PWM_HZ的倍率
    186. for (i = 0; i < SIN_POINTS; i += Sin_Table_Times) //重新计算正弦表,并增加偏移量SIN_OFFSET
    187. {
    188. T_SinTable_Current[i] = T_SinTable[i] * Sin_Cycle_times + SIN_OFFSET;
    189. }
    190. if (WAVE_ON)
    191. {
    192. //PWM IO状态
    193. PWM4 = 0; //设置PWM4 P4.4低电平
    194. P4M1 &= ~0x10; //设置P4.4为推挽输出
    195. P4M0 |= 0x10; //设置P4.4为推挽输出
    196. P_SW2 |= 0x80; //访问xSFR
    197. PWMCR &= ~0x80; //关闭PWM模块
    198. PWMCR &= ~0x40; //禁止PWM计数器归零中断
    199. PWMIF &= ~CBIF; //清除中断标志
    200. PWMCKS = 0x00; //PWM时钟选择
    201. PWMCKS |= PWMCKS_PS; //系统时钟分频作为PWM时钟
    202. PWMC = PWM_Cycle; //设置PWM周期
    203. PWM_Index = 0;
    204. PWM4T1 = 0; //第一次翻转计数器
    205. PWM4T2 = T_SinTable_Current[PWM_Index]; //第二次翻转计数器
    206. PWM_Index += Sin_Table_Times;
    207. PWMCFG &= ~0x04; //配置PWM4的输出初始电平
    208. PWM4CR = 0x08; //PWM4输出到P4.4,无中断
    209. PWMCR |= 0x04; //使能PWM4输出
    210. PWMCR |= 0x40; //允许PWM计数器归零中断
    211. PWMCR |= 0x80; //使能PWM模块
    212. P_SW2 &= ~0x80; //恢复访问XRAM
    213. }
    214. else
    215. {
    216. Wave_OFF();
    217. }
    218. }
    219. /* 输出波形配置 */
    220. void Set_Wave_Shape(void)
    221. {
    222. if(Wave_Shape==1) //方波
    223. PWM_Config();
    224. else if (Wave_Shape == 2) //正弦波
    225. Sin_Wave_Config();
    226. }
    227. /* 用来生成正弦波的SPWM中断
    228. SPWM Interrupt for generating the sine waveform*/
    229. void SPWM_interrupt(void) interrupt SPWM_VECTOR
    230. {
    231. PWMIF &= ~CBIF; //清除中断标志
    232. _push_(P_SW2); //保存SW2设置
    233. P_SW2 |= 0x80; //访问XFR
    234. PWM4T2 = T_SinTable_Current[PWM_Index];
    235. if ((PWM_Index += Sin_Table_Times) >= SIN_POINTS)
    236. PWM_Index = 0;
    237. _pop_(P_SW2); //恢复SW2设置
    238. }
    239. /* 50Hz以下PWM使用Timer1中断产生
    240. Generate PWM below 50Hz by Timer1 Interrupt*/
    241. void TIMER1_interrupt(void) interrupt TIMER_1
    242. {
    243. TR1 = 0;
    244. if (n-- == 0)
    245. {
    246. PWM3 = !PWM3;
    247. Delay200us(); //延时等待PWM3电平变化,200us 24MHz对应4800周期,在计时器初值扣除
    248. if (PWM3)
    249. {
    250. n = n_high;
    251. TH1 = (uint8)(PWM1_high >> 8); //如果是输出高电平,则装载高电平时间。
    252. TL1 = (uint8)PWM1_high;
    253. }
    254. else
    255. {
    256. n = n_low;
    257. TH1 = (uint8)(PWM1_low >> 8); //如果是输出低电平,则装载低电平时间。
    258. TL1 = (uint8)PWM1_low;
    259. }
    260. }
    261. else
    262. {
    263. TH1 = 0x00;
    264. TL1 = 0x00;
    265. }
    266. TF1 = 0;
    267. TR1 = 1;
    268. }

    总结

    较为简单的项目,但让我自己写写不出来,哈哈哈哈哈哈😄😄😄

    还是要多看别人的项目,多学习!

    感谢开源 ~

    项目资料:

    链接:https://pan.baidu.com/s/1hBGWUrWhzagesNPe3dUWkA
    提取码:m493

    如果链接失效而您恰巧需要,可评论或私信

     

  • 相关阅读:
    python 虚拟环境搭建
    236. 二叉树的最近公共祖先
    【历史上的今天】12 月 6 日:微波炉问世;多媒体格式 Mkv 诞生;日立环球存储科技公司成立
    11.30 - 每日一题 - 408
    【送书活动】网络安全(黑客)自学
    Java 生成随机码工具类 线程安全 两种方式
    Flutter 实现“斑马纹”背景(需要变换颜色)
    大一新生HTML期末作业,网页制作作业——明星介绍易烊千玺网站HTML+CSS
    千万级别的表分页查询非常慢,怎么办?
    react的动画
  • 原文地址:https://blog.csdn.net/qq_41650023/article/details/125889968