标题: 关于单片机ADC采样值0-255怎么映射到PWM0-100 [打印本页]

作者: SHANWAZI    时间: 2023-6-4 13:55
标题: 关于单片机ADC采样值0-255怎么映射到PWM0-100
用单片机定时器0做了个PWM模拟输出实现了50HZ输出周期为20Ms,占空比刚刚好对应为0-255级此变量"PWM_DUTY"对应0-255变化脉宽对应0-100变化没什么问题了.问题1:怎么才能结合ADC对外部电位器采样的数值0-255映射到对应的脉宽0-100之间电位器满程调节呢?
问题2:比如需要限制某一个脉宽值比如脉宽1Ms-2.5M变化怎么才能把ADC数值映射到0-255满程调节呢?
sbit PWM_OUT_GPIO=P2^0;


unsigned char PWM_DUTY=128;//此时脉宽刚刚好百分之50
uint8 ADC_Value=0;

void XPT2046_Allot()//XPT2046-ADC芯片数据分频函数
{               
        ADC_Value=Start_XPT2046_ADC(PIN0_0_XP_ADC_8BIT,8);//启动ADC转换芯片函数 此函数第一个形参设置模式和通道 第二个为设置转换的位数 范围8-12
}




void Timer0Init()        //100微秒@12MHz"八位自动"
{
        TMOD &= 0xF0;        //设置定时器模式
        TMOD |= 0x02;        //设置定时器模式
        TL0 = 0xb2;                //设置定时初始值
        TH0 = 0xb2;                //设置定时重载值
        TF0 = 0;                //清除TF0标志
        TR0 = 1;                //定时器0不启动
        ET0 = 1;                //允许定时器0申请中断
        EA  = 1;                //开启所有中断
}


void main()
{
        while(1)
        {
                XPT2046_Allot();//XPT2046-ADC芯片数据分频函数
        }
}

void Timer0Interrupt() interrupt 1
{   
        if(PWM_Cnt<PWM_DUTY)
        {
                PWM_OUT_GPIO=1;
        }
        else
        {
                PWM_OUT_GPIO=0;
        }
        PWM_Cnt++;
}




作者: Hephaestus    时间: 2023-6-4 15:52
总要知道ADC函数输出值的范围吧,不知道这个谁也不会算。
作者: SHANWAZI    时间: 2023-6-4 16:07
Hephaestus 发表于 2023-6-4 15:52
总要知道ADC函数输出值的范围吧,不知道这个谁也不会算。

八位ADC数值0-255
作者: SHANWAZI    时间: 2023-6-4 16:09
SHANWAZI 发表于 2023-6-4 16:07
八位ADC数值0-255

ADC_Value=Start_XPT2046_ADC(PIN0_0_XP_ADC_8BIT,8);“PIN0_0_XP_ADC_8BIT”此变量就是设置ADC位数的目前是八位
作者: Hephaestus    时间: 2023-6-4 16:13
SHANWAZI 发表于 2023-6-4 16:07
八位ADC数值0-255

ADC输出0~255,PWM_DUTY范围0~255你算什么啊?算个寂寞?
作者: wulin    时间: 2023-6-4 16:41
PWM_DUTY = ADC_Value*256/100;
作者: SHANWAZI    时间: 2023-6-4 16:55
wulin 发表于 2023-6-4 16:41
PWM_DUTY = ADC_Value*256/100;

这样写用示波器看占空比最大才40左右
作者: SHANWAZI    时间: 2023-6-4 17:02
wulin 发表于 2023-6-4 16:41
PWM_DUTY = ADC_Value*256/100;

假如ADC输出值为255计算得到的是655.36这?

作者: Hephaestus    时间: 2023-6-4 17:26
SHANWAZI 发表于 2023-6-4 16:55
这样写用示波器看占空比最大才40左右

这不就对了吗,你软件里面最大占空比是255,你以为是100,那么100/255不就是40%吗???
作者: SHANWAZI    时间: 2023-6-4 17:40
Hephaestus 发表于 2023-6-4 17:26
这不就对了吗,你软件里面最大占空比是255,你以为是100,那么100/255不就是40%吗???

那怎么换算过来使他刚刚好ADC值0-255变化 使占空比0-100呢?
作者: SHANWAZI    时间: 2023-6-4 17:45
Hephaestus 发表于 2023-6-4 17:26
这不就对了吗,你软件里面最大占空比是255,你以为是100,那么100/255不就是40%吗???

那比如 我要在某一个占空比之间变化比如默认为1ms-2.5ms 之间变化 怎么才能把这其中的值对应到ADC的0-255电位器满里程调节呢 电位器跳到最小就是1毫秒最大就是2.5毫秒?程序该怎么改?
作者: Hephaestus    时间: 2023-6-4 18:19
SHANWAZI 发表于 2023-6-4 17:40
那怎么换算过来使他刚刚好ADC值0-255变化 使占空比0-100呢?

5楼已经回复你了。
作者: SHANWAZI    时间: 2023-6-4 22:52
Hephaestus 发表于 2023-6-4 18:19
5楼已经回复你了。

感谢感谢  看来还是我的程序有问题 思路不对
作者: yzwzfyz    时间: 2023-6-5 11:06
最简单的方案:
将0-255所对应的PWM0-100值计算出来,建立一个数组。即完成对应关系了。
作者: SHANWAZI    时间: 2023-6-5 16:10
yzwzfyz 发表于 2023-6-5 11:06
最简单的方案:
将0-255所对应的PWM0-100值计算出来,建立一个数组。即完成对应关系了。

老师能否举个例指导一下???
作者: sttt300    时间: 2023-6-5 16:22
  1. sbit PWM_OUT_GPIO=P2^0;


  2. unsigned char PWM_DUTY=50;//此时脉宽刚刚好百分之50
  3. uint8 ADC_Value=0;

  4. void XPT2046_Allot()//XPT2046-ADC芯片数据分频函数
  5. {               
  6.         ADC_Value=Start_XPT2046_ADC(PIN0_0_XP_ADC_8BIT,8);//启动ADC转换芯片函数 此函数第一个形参设置模式和通道 第二个为设置转换的位数 范围8-12
复制代码


作者: sttt300    时间: 2023-6-5 17:11
不知道为什么,直接弄成代码改,只显示一部分,我的建议更改如下:
unsigned char PWM_DUTY=50; 这里的PWM_DUTY应该是0~100,不要做成0~255
PWM_DUTY = ADC_Value * 100 /255,这里出来的就是百分比了,比如ADC值127,算出来就是49,也就是49%
PWM_Cnt++;后面再加一句 if(PWM_Cnt ==100)PWM_Cnt=0;
就是设置100个数,对应100%,和DUTY对比

作者: SHANWAZI    时间: 2023-6-5 17:40
sttt300 发表于 2023-6-5 17:11
不知道为什么,直接弄成代码改,只显示一部分,我的建议更改如下:
unsigned char PWM_DUTY=50; 这里的PWM ...

感谢老师辛勤回复!首先这方法我已经试过了!目的是实现占空比0-99变化很方便。但是还是没达到目的!!!
首先周期是固定的我要让ADC采样到的数值0-255均匀分布出来取对应上这占空比!
比如默认脉宽是1毫秒状态对应电位器为最小值状态。如果调节电位器脉宽从1毫秒开始变化到2.5毫秒也就是电位器拧到最大就是2.5毫秒。问题是这我始终弄不明白??????
作者: SHANWAZI    时间: 2023-6-5 17:41
sttt300 发表于 2023-6-5 17:11
不知道为什么,直接弄成代码改,只显示一部分,我的建议更改如下:
unsigned char PWM_DUTY=50; 这里的PWM ...


目前程序已修改了刚刚好占空比是0-99的。

unsigned char data PWM_DUTY=50;//调节此变量就可以调节占空比0-99变化

void Timer0Interrupt() interrupt 1
{   
        PWM_Cnt++;
        if(PWM_Cnt>=100)//总周期为10ms
        {
                PWM_Cnt=0;
        }

        if(PWM_Cnt<PWM_DUTY)//高电平的半个周期
        {
                PWM_OUT_GPIO=1;
        }
        else
        {
                PWM_OUT_GPIO=0;//低电平的半个周期
        }
}
作者: yzwzfyz    时间: 2023-6-6 15:16
1、周期需要固定时,用一个变量PT表达周期,再用一个变量PA表示高或低电平的宽度。
2、要达到u%(1%)的精度,PA:PT必须<u%。


作者: coody_sz    时间: 2023-6-6 18:19
PWM = ADC*100/255
作者: SHANWAZI    时间: 2023-6-6 18:45
yzwzfyz 发表于 2023-6-6 15:16
1、周期需要固定时,用一个变量PT表达周期,再用一个变量PA表示高或低电平的宽度。
2、要达到u%(1%)的精度 ...

这就有点深奥咯!
作者: yzwzfyz    时间: 2023-6-7 10:33
例:PT=100ms,PA=5ms,用P01做PWM输出。输出脉冲宽度=PA,周期=PT
用定时器做个定时为1ms的中断。中断服务程序这样写:
1、如果PT=PA=0,就复位PT=100ms,PA=5ms,跳至第4步;否则执行下一步。(计时PWM周期到了,复位进入下个周期)
2、PA<>0,执行PA-1;反之PA=0,放弁不做。(计时PWM脉冲输出宽度,计满之后不再计了)
3、PT<>0,执行PT-1;反之PT=0,放弁不做。(计时PWM周期,计满之后不再计了)
4、P01 = PA。(这里需要修改,自己去想)。
5、中断返回退出 。
这里的1ms就是u,1ms/PT=1ms/100ms=1%,就是PWM能达到的精度。
作者: SHANWAZI    时间: 2023-6-7 16:42
yzwzfyz 发表于 2023-6-7 10:33
例:PT=100ms,PA=5ms,用P01做PWM输出。输出脉冲宽度=PA,周期=PT
用定时器做个定时为1ms的中断。中断服 ...

感谢老师辛勤回复




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1