【STC单片机】通过ADC外部输入调节PWM占空比输出并串口打印当前脉冲值
【STC单片机】通过ADC外部输入调节PWM占空比输出并串口打印当前脉冲值
- 相关篇《【STC15系列】P1.3做ADC-使用内部基准计算外部电压并串口打印》
- 《【STC单片机】3路PWM波形输出并串口打印当前脉冲值》
本示例演示基于STC15W408AS单片机,采用自制开发板,使用的是外部晶振16MHz。
- 《【开源分享】自制STC15W408AS开发板》
这篇文章涉及了综合知识的运用。写这一篇文章的初衷是昨天睡觉前的想法,做一个外部可控可调的PWM输出的功能。今天将其程序整理出来并且验证了这一点。
注意:ADC输入引脚不能浮空,不然PWM输出将会是跳动的脉动输出。占空比将是一个随机的状态形式输出。
- 功能实现内容:占空比可调,但是频率是固定的
2.6666KHz
的。如需调整频率,需要修改想要的宏定义的参数。
f=MAIN_Fosc /PWM_DUTY
/**PWM.h文件**/
#define PWM_DUTY 6000 //定义PWM的周期,数值为PCA所选择的时钟脉冲个数。
#define PWM_HIGH_MIN 80 //限制PWM输出的最小占空比, 避免中断里重装参数时间不够。
#define PWM_HIGH_MAX (PWM_DUTY - PWM_HIGH_MIN) //限制PWM输出的最大占空比。
- 设置
2KHz
的频率
//频率f=MAIN_Fosc /PWM_DUTY
#define PWM_DUTY 8000 //定义PWM的周期,数值为PCA所选择的时钟脉冲个数。
#define PWM_HIGH_MIN 80 //限制PWM输出的最小占空比, 避免中断里重装参数时间不够。
#define PWM_HIGH_MAX (PWM_DUTY - PWM_HIGH_MIN) //限制PWM输出的最大占空比。
- 调节定位器时,串口监视器数据动态输出
- 代码完善后,调试完成的输出,串口只是为了方便调试和观察,程序测试OK后,可以去掉串口功能的部分。
采用的是10K定位器接到到P1.3引脚上,作为外部模拟量输入
- 接线图
- ADC的基准电压源采用P1.1口
P1ASF = 0;
Get_ADC10bitResult(1); //改变P1ASF后先读一次并丢弃结果, 让内部的采样电容的电压等于输入值.
Bandgap = Get_ADC10bitResult(1); //读P1.1的电压为基准ADC, P1ASF=0, 0通道的电压值
- PWM输出通道
采用的是PCA0,也可以切换到PCA1,或者PCA2,
- 选择任意其中一组即可。
if(pwm0 >= PWM_HIGH_MAX) pwm0 = PWM_HIGH_MIN;PWMn_Update(PCA0,pwm0);if(pwm1 >= PWM_HIGH_MAX) pwm1 = PWM_HIGH_MIN;PWMn_Update(PCA1,pwm1);if(pwm2 >= PWM_HIGH_MAX) pwm2 = PWM_HIGH_MIN;PWMn_Update(PCA2,pwm2);
- PWM输出引脚
PCA0----P25
PCA1----P26
PCA2----P27
- 示波器采集的数据波形
- 最大占空比时的波形
- 最小占空比
ADC模拟量数据转换
该函数数据类型必须满足被处理的数据,在这个函数实现上掉坑里了,刚开始认为定义一个无符号整型类型来存放就够了,转换出来的值完全不是预期值。
- 该函数实现了,将ADC采集的模拟量的值范围
0~1023
,转换为80 ~ 5920
对应值。
/********************** 模拟量映射函数 ************************/
long map( long x, long in_min, long in_max, long out_min, long out_max)
{return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
- 说明一点的是:
STC15W408AS
只有2
个定时器,全部用完了。定时器0用于ADC采集,定时器2用于串口波特率发生器。STC15W408AS
是没有定时器1
的。 - ADC采集有2个方案
方式一是直接采用读值,另一种是采集16次去平均值。通过宏定义选择其一即可。
#define Cal_MODE 0 //每次测量只读1次ADC. 分辨率0.01V#define Cal_MODE 1 //每次测量连续读16次ADC 再平均计算. 分辨率0.01V
主程序代码
/************* 功能说明 **************双串口全双工中断方式收发通讯程序。
注意:
通过PC向MCU发送数据, MCU收到后通过串口把收到的数据原样返回.******************************************/
#include "config.h"
#include "stdio.h"
#include "USART.h"
#include "PWM.h"
#include "ADC.h"#define Cal_MODE 0 //每次测量只读1次ADC. 分辨率0.01V
// #define Cal_MODE 1 //每次测量连续读16次ADC 再平均计算. 分辨率0.01V
//typedef unsigned char u8;
//typedef unsigned int u16;
//typedef unsigned long u32;volatile bit B_4ms; //1ms标志volatile u16 msecond; //计时
u16 Bandgap; //void delay_ms(unsigned int ms)
{unsigned int i;do{i = MAIN_Fosc / 13000;while(--i) ; //14T per loop}while(--ms);
}
/********************** 模拟量映射函数 ************************/
long map( long x, long in_min, long in_max, long out_min, long out_max)
{return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}//========================================================================
// 函数: void main(void)
// 描述: 主函数。
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2014-11-28
// 备注:
//========================================================================
void main(void)
{u8 i;int Duty ;int j;PCA_Init(); //PCA初始化
// P0M1 = 0; P0M0 = 0; //设置为准双向口
// P1M1 = 0; P1M0 = 0; //设置为准双向口P1M1 = 0x00; P1M0 = 0x00; P1M1 |= (1<<3); // 把ADC口设置为高阻输入P1M0 &= ~(1<<3);P1ASF = (1<<3); //P1.3做ADCADC_CONTR = 0xE0; //90T, ADC power on
// P2M1 = 0; P2M0 = 0; //设置为准双向口P2M1 &= ~(0xe0); //P2.7 P2.6 P2.5 设置为推挽输出P2M0 |= (0xe0);P3M1 = 0; P3M0 = 0; //设置为准双向口
// P4M1 = 0; P4M0 = 0; //设置为准双向口
// P5M1 = 0; P5M0 = 0; //设置为准双向口
// P6M1 = 0; P6M0 = 0; //设置为准双向口
// P7M1 = 0; P7M0 = 0; //设置为准双向口// S1_USE_P30P31();Timer0Init();//定时器0初始化InitSerialPort(); //初始化串口,波特率9600,8bit数据位,1停止位,无校验EA = 1; //允许总中断// PrintString1("STC15F2K60S2 UART1 Test Prgramme!\r\n"); //SUART1发送一个字符串while (1){// delay_ms(500); P10 = !P10;if(pwm0 >= PWM_HIGH_MAX) pwm0 = PWM_HIGH_MAX;// if(pwm1 >= PWM_HIGH_MAX) pwm1 = PWM_HIGH_MAX;
// PWMn_Update(PCA1,pwm1);// if(pwm2 >= PWM_HIGH_MAX) pwm2 = PWM_HIGH_MAX;
// PWMn_Update(PCA2,pwm2);if(B_4ms) //5ms到达标志位{B_4ms = 0;if(++msecond >= 250) //计数到达1S{msecond = 0;#if (Cal_MODE == 0)//=================== 只读1次ADC, 10bit ADC. 分辨率0.01V ===============================P1ASF = 0;Get_ADC10bitResult(1); //改变P1ASF后先读一次并丢弃结果, 让内部的采样电容的电压等于输入值.Bandgap = Get_ADC10bitResult(1); //读P1.1的电压为基准ADC, P1ASF=0, 0通道的电压值P1ASF = 1<<3;j = Get_ADC10bitResult(3); //读外部电压ADC// j = (u16)((u32)j * 507 / Bandgap); //计算外部电压, Bandgap为5.07V, 测电压分辨率0.01Vprintf("\t ADC =%d \t\n",j); pwm0 = (u16)map(j, 0, 1023,80, 5920);//将映射的值赋值给pwm0printf("\t pwm0 =%u \t\n",pwm0 );#endif//==========================================================================//===== 连续读16次ADC 再平均计算. 分辨率0.01V =========#if (Cal_MODE == 1)P1ASF = 0;Get_ADC10bitResult(1); //改变P1ASF后先读一次并丢弃结果, 让内部的采样电容的电压等于输入值.for(j=0, i=0; i<16; i++){j += Get_ADC10bitResult(1); //读P11内部基准ADC, P1ASF=0, 读1通道}Bandgap = j >> 4; //16次平均P1ASF = (1<<3); //P1.3做ADCfor(j=0, i=0; i<16; i++){j += Get_ADC10bitResult(3); //读外部电压ADC}j = j >> 4; //16次平均pwm0= (u16)map(j, 0, 1023, 80, 5920);//将映射的值赋值给pwm0//pwm0 = j;printf("\t pwm0 =%d \t\n",j); //j = (u16)((u32)j * 507 / Bandgap); //计算外部电压, Bandgap为5.07V, 测电压分辨率0.01V#endif //==========================================================================//Duty=map(pwm0, 80, 5920, 0, 100);//将pwm0转换为占空比串口输出PWMn_Update(PCA0,pwm0);//PCA0--P25,PCA2--P26// printf("占空比:%u \r\n",Duty);}}// printf("pwm0:%u \t pwm1:%u \t pwm2:%u\r\n",pwm0,pwm1,pwm2); //SUART1发送一个字符串}
}/********************** Timer0 1ms中断函数 ************************/
void timer0 (void) interrupt 1
{B_4ms = 1; //1ms标志
}
- 程序架构
程序源码
链接:https://pan.baidu.com/s/1pTDkLEafN-MFihnq4l1fNQ
提取码:xonl
【STC单片机】通过ADC外部输入调节PWM占空比输出并串口打印当前脉冲值相关推荐
- ESP32 通过Web图形控件调节PWM占空比输出
ESP32 通过Web图形控件调节PWM占空比输出
- STC单片机通过ADC分段采样读按键实现方法
STC单片机通过ADC分段采样读按键实现方法 ✨在阅读官方FreeRTOS for STC32G12K128开源工程当中有使用到ADC键盘计算键码功能块,底层实现原理也很简单,就是通过串联电阻分压的方 ...
- 【单片机】P3口输入,P1口输出
[单片机]P3口输入,P1口输出 代码详解(方法一) 代码详解(方法二) 代码详解(方法一) #include <reg51.h> #include <intrins.h> / ...
- 串口 单片机 文件_STM32物联网实战项目 HAL裸机开发09 串口打印
就喜欢你关注我- HAL裸机开发09 - 串口打印 综合信息1.获取开发工具 微信公众号后台发送消息 - 工具2.获取开发板 淘宝搜索店铺 - 硬件家园3.快速了解平台 ...
- 单片机ADC采用输入电压范围的调节
本文以STM32F429IGT6单片机为例. STM32F429IGT6有 3 个 ADC,每个 ADC有 12 位.10 位.8 位和 6 位可选,每个ADC有 16 个外部通道.另外还有两个内部 ...
- stc15系列c语言pwm编程,STC单片机C语言程序设计 第25章 STC单片机增强型PWM原理及实现.docx...
STC单片机C语言程序设计 第25章 STC单片机增强型PWM原理及实现 STC单片机增强型PWM发生器原理及应用主 讲:何宾Email:hebin@mail.buct.edu.cn2016.03增强 ...
- YX133具有12位ADC与16位PWM的8位OTP单片机,SOP和QFN小封装单片机适合电子烟等便携产品使用
1.1 产品描述 YX133 是一款以OTP程序为基础的8位微处理器,集成高精准度的8(6+2)通道12位的ADC(VREFHmin=1V),6个8位PWM(或3个16位PWM)生成器,1个硬件比较器 ...
- STC单片机硬件PWM的使用分析
STC单片机(具有PCA功能的),怎么实现可变频率的PWM输出?很多朋友还在使用定时器做可变频PWM, 这里我就介绍怎么使用硬件PWM,在定时器0的分频基数下设计PWM. 首先看CMOD这个寄存器,这 ...
- STC单片机LCD1602四线驱动模式显示ADC采样电压和温度
STC单片机LCD1602四线驱动模式显示ADC采样电压和温度
- 基于STC单片机的两轮平衡车设计
给大家传福利了..后续继续共享基于Arduino/安卓Android/树莓派raspberry等平台的两轮车设计 这是我前年暑假做的一个小项目,今年拿出来整理了下当毕设了(当然毕设里添加了许多其他元素 ...
最新文章
- Objective-C语法简记
- 练习 MongoDB 操作 —— 备份篇(三)
- 简述电子计算机的用途和特点_计算机基础试题及答案
- div.php织梦自定义表判断不能为空,织梦自定义表单字段为必填项的教程
- 给Clouderamanager集群里安装基于Hive的大数据实时分析查询引擎工具Impala步骤(图文详解)...
- python—迭代器
- python多线程gil_Python 多线程、多进程 (一)之 源码执行流程、GIL
- linux修改磁盘盘符,debian下修改磁盘阵列盘符
- 四针手表指的是什么_1000~1500元的男士手表推荐
- Type TIMESTAMP(3) of table field ‘onSellTime‘ does not match with the physical type TIMESTAMP(6)
- 逾期了,如何消除不良记录?
- 去杠杆高歌猛进,借呗会倒闭吗?
- 软件工程第四周作业 - 四则运算
- Angular2 指令
- 基于苹果自研芯片的 Mac 电脑对安全意味着什么?
- H.264 无参考视频质量评价方法 (使用了基于遗传编程方法的符号回归)
- ubuntu jdk install
- python入侵个人电脑的步骤图解台式_入侵渗透专用的python小脚本脚本安全 -电脑资料...
- bzoj3668: [Noi2014]起床困难综合症
- java.lang.NoClassDefFoundError: javax/servlet/http/HttpServlet
热门文章
- 【单位换算】存储单位(bit Byte KB MB GB TB PB EB ZB YB BB)时间单位(ms μs ns ps)长度单位(dm cm mm μm nm pm fm am zm ym)
- 效率工具+WPS复选框显示太阳问题解决方法
- 什么是顶级域名,二级域名和三级域名
- 怎么配置计算机的ip,怎么设置电脑IP地址
- 基于似然比检验统计量的异常轨迹检测
- 计算机字节与位的换算,计算机字节换算(计算机字节换算器)
- LibVLC —— 《基于Qt的LibVLC专业开发技术》视频教程
- 寻址方式(立即寻址、直接寻址、间接寻址、寄存器寻址、寄存器间接寻址)
- Ubuntu 14.04 引导修复(Boot Repair)(双系统修复一)
- 20191124_射雕侠侣和天龙八部小说分类