// 头文件
#include "STC8Hxxx.h"
// 引脚定义
// 宏定义
#define MAIN_Fosc 35000000L // 定义主时钟
// 声明
// 数组
u16 code T_SIN[180] = {
760, 773, 786, 800, 813, 826, 839, 852, 866, 879,
892, 905, 918, 931, 944, 956, 969, 982, 995, 1007,
1020, 1032, 1044, 1057, 1069, 1081, 1093, 1105, 1116, 1128,
1140, 1151, 1162, 1173, 1184, 1195, 1206, 1217, 1227, 1238,
1248, 1258, 1268, 1278, 1287, 1297, 1306, 1315, 1324, 1333,
1341, 1350, 1358, 1366, 1374, 1382, 1389, 1397, 1404, 1411,
1417, 1424, 1430, 1436, 1442, 1448, 1453, 1459, 1464, 1469,
1473, 1478, 1482, 1486, 1490, 1493, 1496, 1500, 1502, 1505,
1507, 1510, 1512, 1513, 1515, 1516, 1517, 1518, 1519, 1519,
1519, 1519, 1519, 1518, 1517, 1516, 1515, 1513, 1512, 1510,
1507, 1505, 1502, 1500, 1496, 1493, 1490, 1486, 1482, 1478,
1473, 1469, 1464, 1459, 1453, 1448, 1442, 1436, 1430, 1424,
1417, 1411, 1404, 1397, 1389, 1382, 1374, 1366, 1358, 1350,
1341, 1333, 1324, 1315, 1306, 1297, 1287, 1278, 1268, 1258,
1248, 1238, 1227, 1217, 1206, 1195, 1184, 1173, 1162, 1151,
1140, 1128, 1116, 1105, 1093, 1081, 1069, 1057, 1044, 1032,
1020, 1007, 995, 982, 969, 956, 944, 931, 918, 905,
892, 879, 866, 852, 839, 826, 813, 800, 786, 773,
};
// 函数
void PWMA_config(void);
// 变量
u8 SineFreq;
u16 SineIndex;
u16 SineSum;
// 函数模块
// PWMA配置
void PWMA_config(void)
{
P_SW2 |= 0x80; // SFR enable
PWMA_PSCR = 0x0000; // 预分频寄存器, 分频 Fck_cnt = Fck_psc/(PSCR[15:0}+1), 边沿对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)), 中央对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)*2).
PWMA_DTR = 17; // 死区时间配置, n=0~127: DTR= n T, 0x80 ~(0x80+n), n=0~63: DTR=(64+n)*2T,
// 0xc0 ~(0xc0+n), n=0~31: DTR=(32+n)*8T, 0xE0 ~(0xE0+n), n=0~31: DTR=(32+n)*16T,
PWMA_ARR = 1519; // 自动重装载寄存器, 控制PWM周期
PWMA_CCMR1 = 0x68; // 通道模式配置, PWM模式1, 预装载允许
PWMA_CCMR2 = 0x68;
SineIndex = 0;
SineSum = 0;
PWMA_CCR1 = T_SIN[0]; // 计数器比较值, 控制占空比
PWMA_CCR2 = T_SIN[89]; //
PWMA_CCER1 = 0x55; // 配置通道输出使能和极性
PWMA_CCER2 = 0x05; // 配置通道输出使能和极性
PWMA_BKR = 0x80; // 主输出使能 相当于总开关
PWMA_IER = 0x01; // 使能更新中断
PWMA_CR1 = 0x81; // 使能计数器, 允许自动重装载寄存器缓冲, 边沿对齐模式, 向上计数, bit7=1:写自动重装载寄存器缓冲(本周期不会被打扰), =0:直接写自动重装载寄存器本(周期可能会乱掉)
PWMA_ENO = 0x3F; // IO输出PWM允许, bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P, bit3: ENO2N, bit2: ENO2P, bit1: ENO1N, bit0: ENO1P
PWMA_PS = (0<<6)+(0<<4)+(0<<2)+0; //选择IO, 4项从高到低(从左到右)对应PWM1 PWM2 PWM3 PWM4, 0:选择P1.x, 1:选择P2.x, 2:选择P6.x,
}
// PWMA_PS PWM4N PWM4P PWM3N PWM3P PWM2N PWM2P PWM1N PWM1P
// 00 P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0
// 01 P2.7 P2.6 P2.5 P2.4 P2.3 P2.2 P2.1 P2.0
// 02 P6.7 P6.6 P6.5 P6.4 P6.3 P6.2 P6.1 P6.0
// 03 P3.3 P3.4 -- -- -- -- -- --
// 主函数
void main(void)
{
SineFreq = 50; // 给定一个正弦波频率, 1~255Hz, 改变这个值即可改变输出正弦波频率, 并且相位连续.
PWMA_config();
EA = 1;
// P10 11 13 54 推挽输出
P1M0 |= 0x0b; P1M1 &= ~0x0b;
P5M0 |= 0x10; P5M1 &= ~0x10;
while (1)
{
}
}
// 中断服务函数
// 描述: PWMA中断处理程序. 捕获数据通过 TIM1-> CCRnH / TIM1-> CCRnL 读取
void PWMA_ISR(void) interrupt PWMA_VECTOR
{
u8 sr1;
sr1 = PWMA_SR1; // 为了快速, 中断标志用一个局部变量处理
PWMA_SR1 = 0; // 清除中断标志
PWMA_SR2 = 0; // 清除中断标志
if(sr1 & 0x01)
{
SineSum += (u16)SineFreq;
if(SineSum >= 11520) SineSum -= 11520;
SineIndex = SineSum / 64;
PWMA_CCR1 = T_SIN[SineIndex];
PWMA_CCR2 = T_SIN[(89 - SineIndex)]; // 反相
}
}
这是我用AI8H2K17U芯片做的单极倍频的程序 最终会生成50Hz正弦波
是用8HPWM 3相的案例改成的两相 根据晶振和公式重新计算了数组和ARR CCR
但是最终测试的时候 方波都ok 测试正弦波的时候输出的不是标准正弦波 整个波形变形
是只有增强型PWM的芯片才能做两路互补SPWM么
有无8H输出两路互补SPWM的案例 |