找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1675|回复: 23
收起左侧

关于单片机ADC采样值0-255怎么映射到PWM0-100

[复制链接]
ID:232366 发表于 2023-6-4 13:55 | 显示全部楼层 |阅读模式
用单片机定时器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++;
}



回复

使用道具 举报

ID:883242 发表于 2023-6-4 15:52 | 显示全部楼层
总要知道ADC函数输出值的范围吧,不知道这个谁也不会算。
回复

使用道具 举报

ID:232366 发表于 2023-6-4 16:07 | 显示全部楼层
Hephaestus 发表于 2023-6-4 15:52
总要知道ADC函数输出值的范围吧,不知道这个谁也不会算。

八位ADC数值0-255
回复

使用道具 举报

ID:232366 发表于 2023-6-4 16:09 | 显示全部楼层

ADC_Value=Start_XPT2046_ADC(PIN0_0_XP_ADC_8BIT,8);“PIN0_0_XP_ADC_8BIT”此变量就是设置ADC位数的目前是八位
回复

使用道具 举报

ID:883242 发表于 2023-6-4 16:13 | 显示全部楼层

ADC输出0~255,PWM_DUTY范围0~255你算什么啊?算个寂寞?
回复

使用道具 举报

ID:213173 发表于 2023-6-4 16:41 | 显示全部楼层
PWM_DUTY = ADC_Value*256/100;
回复

使用道具 举报

ID:232366 发表于 2023-6-4 16:55 来自手机 | 显示全部楼层
wulin 发表于 2023-6-4 16:41
PWM_DUTY = ADC_Value*256/100;

这样写用示波器看占空比最大才40左右
回复

使用道具 举报

ID:232366 发表于 2023-6-4 17:02 来自手机 | 显示全部楼层
wulin 发表于 2023-6-4 16:41
PWM_DUTY = ADC_Value*256/100;

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

使用道具 举报

ID:883242 发表于 2023-6-4 17:26 | 显示全部楼层
SHANWAZI 发表于 2023-6-4 16:55
这样写用示波器看占空比最大才40左右

这不就对了吗,你软件里面最大占空比是255,你以为是100,那么100/255不就是40%吗???
回复

使用道具 举报

ID:232366 发表于 2023-6-4 17:40 来自手机 | 显示全部楼层
Hephaestus 发表于 2023-6-4 17:26
这不就对了吗,你软件里面最大占空比是255,你以为是100,那么100/255不就是40%吗???

那怎么换算过来使他刚刚好ADC值0-255变化 使占空比0-100呢?
回复

使用道具 举报

ID:232366 发表于 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毫秒?程序该怎么改?
回复

使用道具 举报

ID:883242 发表于 2023-6-4 18:19 | 显示全部楼层
SHANWAZI 发表于 2023-6-4 17:40
那怎么换算过来使他刚刚好ADC值0-255变化 使占空比0-100呢?

5楼已经回复你了。
回复

使用道具 举报

ID:232366 发表于 2023-6-4 22:52 来自手机 | 显示全部楼层
Hephaestus 发表于 2023-6-4 18:19
5楼已经回复你了。

感谢感谢  看来还是我的程序有问题 思路不对
回复

使用道具 举报

ID:123289 发表于 2023-6-5 11:06 | 显示全部楼层
最简单的方案:
将0-255所对应的PWM0-100值计算出来,建立一个数组。即完成对应关系了。
回复

使用道具 举报

ID:232366 发表于 2023-6-5 16:10 | 显示全部楼层
yzwzfyz 发表于 2023-6-5 11:06
最简单的方案:
将0-255所对应的PWM0-100值计算出来,建立一个数组。即完成对应关系了。

老师能否举个例指导一下???
回复

使用道具 举报

ID:647261 发表于 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
复制代码

回复

使用道具 举报

ID:647261 发表于 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对比
回复

使用道具 举报

ID:232366 发表于 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毫秒。问题是这我始终弄不明白??????
回复

使用道具 举报

ID:232366 发表于 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;//低电平的半个周期
        }
}
回复

使用道具 举报

ID:123289 发表于 2023-6-6 15:16 | 显示全部楼层
1、周期需要固定时,用一个变量PT表达周期,再用一个变量PA表示高或低电平的宽度。
2、要达到u%(1%)的精度,PA:PT必须<u%。

回复

使用道具 举报

ID:1034262 发表于 2023-6-6 18:19 | 显示全部楼层
PWM = ADC*100/255
回复

使用道具 举报

ID:232366 发表于 2023-6-6 18:45 来自手机 | 显示全部楼层
yzwzfyz 发表于 2023-6-6 15:16
1、周期需要固定时,用一个变量PT表达周期,再用一个变量PA表示高或低电平的宽度。
2、要达到u%(1%)的精度 ...

这就有点深奥咯!
回复

使用道具 举报

ID:123289 发表于 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能达到的精度。
回复

使用道具 举报

ID:232366 发表于 2023-6-7 16:42 | 显示全部楼层
yzwzfyz 发表于 2023-6-7 10:33
例:PT=100ms,PA=5ms,用P01做PWM输出。输出脉冲宽度=PA,周期=PT
用定时器做个定时为1ms的中断。中断服 ...

感谢老师辛勤回复
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表