用于 LED 调光异常行为的 PWM
PWM for LED dimming unusual behavior
我创建了一个函数,其中在输出端 (PORTD) 生成 PWM 信号,而无需使用 PIC 微控制器 (PIC18F452) 内部的 PWM 控制寄存器。为了慢慢调暗连接在输出端的 LED,我试图增加脉冲从一个周期的 0% 前进到方波一个周期的 100% 所需的时间,同时使方波频率恒定。一切都应该按计划进行,除了第二个参数被传递到 pwm
函数,当从 655 变为 666 时(即,当占空比为 65% 时)以某种方式重置。在此事件之后,传递给 pwm
函数的值从 0 开始。它不应在从 655 到 656 的转换时重置,而是在从 1000 到 1001 的转换时重置。
void main(void) {
TRISD = 0x00; //port D set as output
LATD = 0x00; //port D output set LOW
unsigned int width = 1000; // length of T_on + T_off
unsigned int j;
unsigned int res;
while(1){
for (j = 1; j <= width; j++){
res = (unsigned int)((j*100)/width);
pwm(&LATD, res);
}
}
return;
}
void pwm(volatile unsigned char *lat, unsigned int cycle){
if(cycle > 100){ // reset the "cycle"
cycle = 100;
}
unsigned int i = 1;
while(i<=(cycle)){ // T_on
*lat = 0x01;
i++;
}
unsigned int j = 100-cycle;
while(j){ // T_off
*lat = 0;
j--;
}
return;
}
至于程序本身,它应该是这样工作的:
- 传递给
pwm
函数的第二个参数是占空比(以%为单位),它从0变为100
- 使用变量“width”控制占空比从 0% 到 100% 所需的时间(width = 100 表示最快时间,高于此值的所有时间都被认为是从 0% 到 100% 的逐渐变慢的时间)
- 表达式
((j*100)/width)
在 pwm
函数内的“while”循环内用作步骤变量:
- 如果
width = 100
,每增加“j”步长就增加
- 如果
width = 1000
,每增加10个“j”,step就会增加,
等等
- PORTD作为它的地址传入函数,而在函数
pwm
中,这个地址是通过指针变量lat
操作的
至于问题本身,我只能假设两种可能:函数pwm
的第二个参数的数据类型不正确,或者PIC微处理器内部存在一些未知的限制。
此外,这里是 PIC 的配置位(设备特定寄存器)的定义,位于该程序中包含的 int 头文件中:https://imgur.com/a/UDYifgN
程序应该这样运行:https://vimeo.com/488207207
这是程序当前的运行方式:https://vimeo.com/488207746
问题是 16 位溢出:
res = (unsigned int)((j*100)/width);
如果j
大于655则j*100的计算结果大于16位。将其切换为 32 位。或者更容易让你的循环从 0...100 for res
.
例如
for (res = 0; res <= 100; res++){
pwm(&LATD, res);
}
我创建了一个函数,其中在输出端 (PORTD) 生成 PWM 信号,而无需使用 PIC 微控制器 (PIC18F452) 内部的 PWM 控制寄存器。为了慢慢调暗连接在输出端的 LED,我试图增加脉冲从一个周期的 0% 前进到方波一个周期的 100% 所需的时间,同时使方波频率恒定。一切都应该按计划进行,除了第二个参数被传递到 pwm
函数,当从 655 变为 666 时(即,当占空比为 65% 时)以某种方式重置。在此事件之后,传递给 pwm
函数的值从 0 开始。它不应在从 655 到 656 的转换时重置,而是在从 1000 到 1001 的转换时重置。
void main(void) {
TRISD = 0x00; //port D set as output
LATD = 0x00; //port D output set LOW
unsigned int width = 1000; // length of T_on + T_off
unsigned int j;
unsigned int res;
while(1){
for (j = 1; j <= width; j++){
res = (unsigned int)((j*100)/width);
pwm(&LATD, res);
}
}
return;
}
void pwm(volatile unsigned char *lat, unsigned int cycle){
if(cycle > 100){ // reset the "cycle"
cycle = 100;
}
unsigned int i = 1;
while(i<=(cycle)){ // T_on
*lat = 0x01;
i++;
}
unsigned int j = 100-cycle;
while(j){ // T_off
*lat = 0;
j--;
}
return;
}
至于程序本身,它应该是这样工作的:
- 传递给
pwm
函数的第二个参数是占空比(以%为单位),它从0变为100 - 使用变量“width”控制占空比从 0% 到 100% 所需的时间(width = 100 表示最快时间,高于此值的所有时间都被认为是从 0% 到 100% 的逐渐变慢的时间)
- 表达式
((j*100)/width)
在pwm
函数内的“while”循环内用作步骤变量:
- 如果
width = 100
,每增加“j”步长就增加 - 如果
width = 1000
,每增加10个“j”,step就会增加, 等等
- PORTD作为它的地址传入函数,而在函数
pwm
中,这个地址是通过指针变量lat
操作的
至于问题本身,我只能假设两种可能:函数pwm
的第二个参数的数据类型不正确,或者PIC微处理器内部存在一些未知的限制。
此外,这里是 PIC 的配置位(设备特定寄存器)的定义,位于该程序中包含的 int 头文件中:https://imgur.com/a/UDYifgN
程序应该这样运行:https://vimeo.com/488207207
这是程序当前的运行方式:https://vimeo.com/488207746
问题是 16 位溢出:
res = (unsigned int)((j*100)/width);
如果j
大于655则j*100的计算结果大于16位。将其切换为 32 位。或者更容易让你的循环从 0...100 for res
.
例如
for (res = 0; res <= 100; res++){
pwm(&LATD, res);
}