当前位置: 首页 > news >正文

九齐单片机2路PWM控制输出实现指南

详细介绍如何在九齐单片机上实现2路PWM控制输出,包括硬件配置、寄存器设置和代码实现。

一、九齐单片机PWM模块概述

九齐单片机(如NY8A/B系列)通常内置1-2个PWM模块,具有以下特点:

  • 8位或10位分辨率
  • 可编程频率和占空比
  • 可配置输出引脚
  • 支持互补输出和死区控制(部分型号)
  • 与定时器模块共享资源

二、硬件配置

1. 典型应用电路

+Vcc (3.3V/5V)│├─[电阻]─┬─ PWM0输出引脚(如PA0)│        └─ 负载(LED/电机)│├─[电阻]─┬─ PWM1输出引脚(如PA1)│        └─ 负载(LED/电机)│└─ 九齐单片机├─ Vss(地)├─ XTAL(晶振)└─ 其他外围电路

2. 引脚分配示例(NY8A051D)

PWM通道 默认引脚 可重映射引脚
PWM0 PA0 PA2, PB0
PWM1 PA1 PA3, PB1

三、寄存器配置

1. 关键寄存器

寄存器名 功能描述 地址(示例)
PWM0CON PWM0控制寄存器 0x0B
PWM0DUTY PWM0占空比寄存器 0x0C
PWM0PRD PWM0周期寄存器 0x0D
PWM1CON PWM1控制寄存器 0x0E
PWM1DUTY PWM1占空比寄存器 0x0F
PWM1PRD PWM1周期寄存器 0x10
PIOA/B 端口A/B数据寄存器 0x00/0x02
PIOACON/B 端口A/B控制寄存器 0x08/0x09

2. PWM控制寄存器位定义(PWMxCON)

名称 功能描述
7 EN PWM使能位(1=使能, 0=禁用)
6 OE 输出使能(1=输出, 0=高阻)
5 POL 极性选择(1=反相, 0=同相)
4-0 CKS 时钟预分频选择(见下表)

3. 时钟预分频选择(CKS)

CKS[4:0] 分频系数 说明
00000 1 不分频
00001 2 ÷2
00010 4 ÷4
00011 8 ÷8
00100 16 ÷16
... ... ...
11111 64 ÷64

四、代码实现

1. 完整代码示例(NY8A051D, 2路PWM)

#include <ny8.h>
#include "ny8_constant.h"// 系统时钟定义(Hz)
#define SYSCLK 4000000L// PWM周期计算(单位:系统时钟周期)
// 目标频率1kHz: 周期 = SYSCLK / 1000 = 4000
#define PWM_PERIOD 4000// 函数声明
void SystemInit(void);
void PWM0_Init(void);
void PWM1_Init(void);
void Update_PWM_Duty(uint8_t ch, uint16_t duty);void main(void)
{SystemInit();PWM0_Init();PWM1_Init();// 初始占空比Update_PWM_Duty(0, 1000);  // PWM0: 25% (1000/4000)Update_PWM_Duty(1, 2000);  // PWM1: 50% (2000/4000)while(1){// 主循环中可以动态改变占空比// 例如: 呼吸灯效果for(uint16_t i=0; i<PWM_PERIOD; i++){Update_PWM_Duty(0, i);Update_PWM_Duty(1, PWM_PERIOD - i);_delay_ms(1);}for(uint16_t i=PWM_PERIOD; i>0; i--){Update_PWM_Duty(0, i);Update_PWM_Duty(1, PWM_PERIOD - i);_delay_ms(1);}}
}// 系统初始化
void SystemInit(void)
{// 设置系统时钟(4MHz)DISI();CLKMD = 0x00;  // 内部RC振荡器CLKMDbits.IE = 0;INTE = 0;PCON = 0;DISI();// 设置I/O为输出IOSTA = 0x03;  // PA0(0), PA1(1)为输出PORTA = 0x00;  // 初始低电平
}// PWM0初始化
void PWM0_Init(void)
{// 设置PWM0引脚(PA0)为输出IOSTA |= 0x01;  // PA0输出// 配置PWM0PWM0PRD = PWM_PERIOD - 1;  // 周期值(0-based)PWM0DUTY = 0;              // 初始占空比0// 控制寄存器: 使能PWM, 输出使能, 同相, 不分频PWM0CON = (1<<7) | (1<<6) | (0<<5) | 0x00;
}// PWM1初始化
void PWM1_Init(void)
{// 设置PWM1引脚(PA1)为输出IOSTA |= 0x02;  // PA1输出// 配置PWM1PWM1PRD = PWM_PERIOD - 1;  // 周期值(0-based)PWM1DUTY = 0;              // 初始占空比0// 控制寄存器: 使能PWM, 输出使能, 同相, 不分频PWM1CON = (1<<7) | (1<<6) | (0<<5) | 0x00;
}// 更新PWM占空比
// ch: 0=PWM0, 1=PWM1
// duty: 0-PWM_PERIOD之间的占空比值
void Update_PWM_Duty(uint8_t ch, uint16_t duty)
{if(duty > PWM_PERIOD) duty = PWM_PERIOD;if(ch == 0){PWM0DUTY = duty;}else if(ch == 1){PWM1DUTY = duty;}
}

2. 关键函数说明

PWM初始化函数

void PWM0_Init(void)
{IOSTA |= 0x01;        // 设置PA0为输出PWM0PRD = 3999;       // 周期=4000 (0-3999)PWM0DUTY = 0;         // 初始占空比0PWM0CON = 0b11000000; // 使能+输出使能+同相+不分频
}

占空比更新函数

void Set_PWM_Duty(uint8_t channel, uint16_t duty)
{if(duty > PWM_PERIOD) duty = PWM_PERIOD;switch(channel){case 0: PWM0DUTY = duty; break;case 1: PWM1DUTY = duty; break;}
}

呼吸灯效果实现

void Breathing_LED_Effect(void)
{for(int i=0; i<PWM_PERIOD; i++){Set_PWM_Duty(0, i);     // PWM0渐亮Set_PWM_Duty(1, PWM_PERIOD-i); // PWM1渐暗Delay_ms(2);}for(int i=PWM_PERIOD; i>0; i--){Set_PWM_Duty(0, i);     // PWM0渐暗Set_PWM_Duty(1, PWM_PERIOD-i); // PWM1渐亮Delay_ms(2);}
}

五、应用场景

1. LED调光控制

// 设置LED亮度(0-100%)
void Set_LED_Brightness(uint8_t percent)
{uint16_t duty = (uint16_t)((PWM_PERIOD * percent) / 100);Set_PWM_Duty(0, duty);
}

2. 直流电机控制

// 控制电机速度和方向
void Motor_Control(int8_t speed)
{if(speed > 0) {// 正转Set_PWM_Duty(0, speed * 40);  // 0-100%映射到0-4000Set_PWM_Duty(1, 0);} else if(speed < 0) {// 反转Set_PWM_Duty(0, 0);Set_PWM_Duty(1, (-speed) * 40);}else {// 停止Set_PWM_Duty(0, 0);Set_PWM_Duty(1, 0);}
}

3. 蜂鸣器音调控制

// 播放指定频率声音
void Buzzer_Beep(uint16_t freq, uint16_t duration_ms)
{// 计算周期值: SYSCLK / (freq * 2)uint16_t period = SYSCLK / (freq * 2);PWM0PRD = period - 1;Set_PWM_Duty(0, period / 2);  // 50%占空比Delay_ms(duration_ms);// 关闭蜂鸣器Set_PWM_Duty(0, 0);
}

参考代码 九齐单片机2路PWM控制输出 www.youwenfan.com/contentcns/183127.html

六、调试技巧

  1. 示波器检查

    • 使用示波器检查PWM输出波形
    • 验证频率和占空比是否符合预期
    • 检查上升/下降时间
  2. 常见问题解决

    问题现象 可能原因 解决方案
    无输出 引脚配置错误 检查IOSTA和PIOACON设置
    PWM未使能 确认PWMxCON.EN=1
    输出被禁用 确认PWMxCON.OE=1
    频率偏差 时钟源错误 检查CLKMD设置
    分频系数错误 验证CKS设置
    占空比异常 寄存器值超限 确保duty ≤ PRD
    数据类型错误 使用uint16_t存储duty值
  3. 低功耗优化

    // 进入空闲模式
    void Enter_Idle_Mode(void)
    {PCONbits.IDLE = 1;  // 进入空闲模式NOP();NOP();
    }// 在PWM配置中使用低功耗模式
    PWM0CON |= (1<<3);  // 启用低功耗模式(如果支持)
    

七、高级应用

1. 互补输出与死区控制

// 配置互补PWM输出(需要支持此功能的型号)
void Complementary_PWM_Init(void)
{// 设置PWM0和PWM1为互补输出PWM0CON |= (1<<4);  // 使能互补模式PWM0CON |= (1<<2);  // 使能死区PWM0DBC = 20;       // 死区时间(时钟周期数)
}

2. PWM捕获功能

// 配置PWM输入捕获
void PWM_Capture_Init(void)
{// 设置PA2为PWM输入捕获IOSTA &= ~0x04;     // PA2输入IC0CON = 0b10000100; // 上升沿捕获, 使能捕获// 使能捕获中断INTE |= 0x01;        // 使能IC0中断_emi = 1;            // 全局中断使能
}// 捕获中断服务函数
void ISR_IC0(void) interrupt
{static uint16_t rise_time, fall_time;if(IC0CONbits.EDGE) {// 上升沿捕获rise_time = IC0BUF;} else {// 下降沿捕获fall_time = IC0BUF;uint16_t pulse_width = fall_time - rise_time;// 处理脉冲宽度...}IC0CONbits.EDGE ^= 1;  // 切换边沿IC0CONbits.IF = 0;     // 清除中断标志
}

八、不同型号配置差异

型号 PWM通道 分辨率 特殊功能 推荐应用
NY8A050D 1路 8位 基本PWM LED调光
NY8A051D 2路 8位 独立控制 双电机控制
NY8B062A 2路 10位 互补输出+死区 半桥驱动
NY8B072E 3路 10位 中心对齐模式 三相电机控制

九、总结

九齐单片机的2路PWM控制实现相对简单,主要步骤包括:

  1. 配置I/O引脚为PWM输出
  2. 设置PWM周期寄存器(PRD)
  3. 设置PWM占空比寄存器(DUTY)
  4. 配置控制寄存器(CON)使能PWM
  5. 在应用中动态更新占空比
http://www.jsqmd.com/news/512089/

相关文章:

  • Glyph视觉推理模型效果对比:传统方法与视觉压缩方案实测
  • [Hang Detect] SYS_HANG_DETECT_RAW中的task info
  • 【Unity】深入解析Vector3与Quaternion:从基础操作到实战应用
  • Qwen-Image效果实测:在40GB数据盘中高效缓存Qwen-VL权重与高频测试图像集
  • Fun-ASR语音识别系统快速上手:支持31种语言,热词增强精准识别
  • 新手友好:GTE文本向量中文大模型Web应用部署全攻略
  • 3月聚焦:优质轻集料混凝土批发厂商哪家好的优选名单,行业内轻集料混凝土精选优质品牌助力工程采购 - 品牌推荐师
  • 用3D Gaussian Splatting自制3D模型:从视频到点云的完整流程(Colmap+FFmpeg)
  • InstructGPT实战解析:从SFT到RLHF的完整训练流程
  • Pixel Dimension Fissioner应用案例:为独立游戏开发者生成100+任务描述
  • Vivado IP许可缺失:从报错到成功生成Bitstream的实战指南
  • Fish-Speech-1.5语音合成与Stable Diffusion联动:打造多媒体内容生产流水线
  • K8s详解
  • 嵌入式事件驱动+状态机轻量级框架设计
  • SmallThinker-3B-Preview惊艳效果:建筑图纸合规性审查中的条款引用与逻辑溯源
  • UniApp左右滑动切换页面避坑指南:从组件到scroll-view的全面解析
  • 从漏洞扫描到责任界定:用Nessus扫描报告讲清楚A、B、C公司的安全协作故事
  • RoboTwin 2.0:如何用多模态大模型与闭环反馈,为异构双臂机器人“量产”高质量仿真数据
  • SenseVoice Small实战案例:科研访谈录音→生成可引用的结构化引文文本
  • 半导体晶圆测量新手必看:3种主流设备实测对比与选型指南
  • STM32_ADC_模数转换器
  • Linux操作系统之线程:线程控制
  • 电机控制必学:Clarke和Park变换的5分钟快速记忆法(附MATLAB验证代码)
  • Bambu Studio 3D打印切片软件:从入门到精通的完整指南
  • STM32_ADC_寄存器操作
  • 基于RABC的权限控制设计
  • 数据库设计原则
  • Qwen2.5-VL-7B-Instruct保姆级教程:对话历史管理、一键清空操作
  • 总结上海移民中介服务费用情况,多少钱才合理 - mypinpai
  • WangEditor — 轻量级富文本编辑器的核心功能与实战应用