单片机定时器产生pwm

本文介绍了一种使用AVR单片机M128通过定时器产生不同占空比PWM波形的方法。代码中详细展示了如何初始化端口、设置定时器参数,并通过切换OCR1A寄存器的值来改变PWM信号的占空比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
利用定时器产生不同占空比的PWM波形输出.
//ICC-AVR application builder : 2006-7-14 16:54:48
// Target : M128
// Crystal: 14.7456Mhz

#include <iom128v.h>
#include <macros.h>

//#define PWM_select  (PINC&3)

void port_init(void)
{
 PORTA = 0xFF;
 DDRA  = 0x00;
 PORTB = 0xFF;
 DDRB  = 0xFF;
 PORTC = 0x03; //输入,上拉电阻使能
 DDRC  = 0xFf;
 PORTD = 0xFF;
 DDRD  = 0x00;
 PORTE = 0xFF;
 DDRE  = 0x00;
 PORTF = 0xFF;
 DDRF  = 0x00;
 PORTG = 0x1F;
 DDRG  = 0x00;
}

//TIMER1 initialisation - prescale:8
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 1Hz
// actual value: Out of range
void timer1_init(void)
{
 TCCR1B = 0x00; //stop
 TCNT1H = 0x00 /*INVALID SETTING*/; //setup
 TCNT1L = 0x00 /*INVALID SETTING*/;
 OCR1AH = 0x00 /*INVALID SETTING*/;
 OCR1AL = 0x00 /*INVALID SETTING*/;
 OCR1BH = 0x00 /*INVALID SETTING*/;
 OCR1BL = 0x00 /*INVALID SETTING*/;
 OCR1CH = 0x00 /*INVALID SETTING*/;
 OCR1CL = 0x00 /*INVALID SETTING*/;
 ICR1H  = 0x00 /*INVALID SETTING*/;
 ICR1L  = 0x00 /*INVALID SETTING*/;
 TCCR1A = 0x91;//8位PWM,
 TCCR1B = 0x02; //预分频8
}

//call this routine to initialise all peripherals
void init_devices(void)
{
 //stop errant interrupts until set up
 CLI(); //disable all interrupts
 XDIV  = 0x00; //xtal divider
 XMCRA = 0x00; //external memory
 port_init();
 timer1_init();

 MCUCR = 0x00;
 EICRA = 0x00; //extended ext ints
 EICRB = 0x00; //extended ext ints
 EIMSK = 0x00;
 TIMSK = 0x00; //timer interrupt sources
 ETIMSK = 0x00; //extended timer interrupt sources
 SEI(); //re-enable interrupts
 //all peripherals are now initialised
}

void main(void)

  unsigned int oldtogs; //storage for past walue of input
unsigned int PWM_select=3;
  port_init();
  timer1_init();
  init_devices();
 
  while(1)
  {
 //   if (PWM_select !=oldtogs)
// {
//    oldtogs=PWM_select;
   switch (PWM_select)
   {
     case 0:
    OCR1A=25;  //10%
break;
     case 1:
    OCR1A=51;  //20%
break;
 case 2:
    OCR1A=76;  //30%
break;
 case 3:
    OCR1A=102;  //40%
break;
}
// }
   }
}  
 
### 51单片机使用定时器生成PWM信号方法 对于51单片机而言,由于其硬件结构相对简单,并未提供专门用于PWM输出的功能模块。因此,在这类设备上实现PWM通常依赖于软件配合定时器中断来完成。 #### 实现思路 核心思想是在设定的时间间隔内改变I/O口的状态,从而形成周期性的高低电平变化,即PWM波形。具体来说,可以设置两个时间参数:一个是整个周期的时间长度T;另一个是高电平持续的时间tH。通过调整这两个参数的比例即可调节PWM的占空比[^1]。 #### 软件设计要点 为了精确控制上述提到的时间参数,需充分利用51系列内部集成的一个或多通道16位自动重装载计数型定时/计数器资源。编程时一般会采用如下策略: - **初始化阶段** - 配置好所需使用的端口方向为输出模式; - 设置合适的晶振频率以及相应的机器周期数值作为基础时钟源; - 计算并加载适当初值到THx(高位)和TLx(低位),这里"x"代表具体的定时器编号; - 开启对应定时器溢出中断允许标志位EA=1, ETx=1 (x表示特定定时器号); - **中断服务程序(ISR)处理逻辑** - 当发生一次完整的定时事件后进入此函数体内执行相应操作; - 判断当前处于哪个状态(比如上升沿还是下降沿),据此切换指定GPIO引脚上的电压等级; - 更新下次触发条件所需的计数值; 下面给出一段基于C语言编写的简化版代码片段用来说明这一过程: ```c #include <reg52.h> sbit PWM_OUT = P1^0; //定义PWM输出管脚 void Timer_Init(void){ TMOD &= 0xF0; //清零TMOD低四位 TMOD |= 0x01; //选择工作方式1(Timer Mode 1) TH0=(65536-500)/256;//计算初始值给定载荷寄存器 TL0=(65536-500)%256; TR0=1; //启动Timer0 } unsigned char flag=0; void main(){ EA=1; //使能全局中断 ET0=1; //使能Timer0中断 Timer_Init(); //调用初始化子程序 while(1){ //主循环等待中断响应 ; } } // 中断服务程序 void timer0_isr() interrupt 1 { static unsigned int count=0; if (++count >= 200) { // 假设总周期为200个单位时间内 count = 0; flag ^= 1; // 反转flag变量 } if(flag==0){ PWM_OUT=0; // 输出低电平 }else{ PWM_OUT=1; // 输出高电平 } } ``` 这段代码展示了如何利用8051架构下的定时器0来创建一个简单的PWM输出机制。其中`timer0_isr()`函数负责每次定时器溢出后的动作判断与IO电平转换,而外部main函数则保持最小化以便让CPU专注于ISR调度管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值