单片机接口与技术 实验05 定时器/计数器

目录

1、 实验目的:

2、实验内容: 

(1)05-1产生方波:

代码:

电路图:

编译:

仿真:

(2)05-2直流电机调速:

代码:

电路图:

编译:

仿真:

电路板-单片机实体:


1、 实验目的:

(1)学习51单片机定时器/计数器的使用方法;

(2)学习定时器实现PWM电机调速的方法。

(3)继续巩固lcd1602的使用。

(4)学习模块化开发的方法

2、实验内容: 

(1)05-1产生方波:

设单片机晶振频率为11.0592MHz,请编写程序利用定时器/计数器T0工作在方式1,在P2.7引脚上连续输出周期2秒的方波。在proteus里使用虚拟示波器查看输出波形。将程序烧写进电路板,连接好(风扇)直流电机(J4插座),在电路板中右部的P1处将P27与A/电机短接。观察风扇转动情况。

要求:定时器采用查询和中断两种方式,分别编写程序实现以上功能。

思考题:此时风扇为什么忽转忽停?

代码:

#define VERSION 2 // 版本1为查询 版本2为中断

#include <reg51.h>
typedef unsigned char uchar;
sbit P2_7 = P2^7;
uchar count = 0;

void main(void)
{
	TMOD = 0x01;
	TR0 = 1;
#if VERSION == 1 //查询方式
	while (1)
	{
		TH0 = 0x3c;
		TL0 = 0xb0; // 65536 - 50000 --> 3CB0H
		while (!TF0);
		TF0 = 0;
		count++;
		if (count == 20) // 50ms * 20 = 1s
		{
			P2_7 = !P2_7; // 一秒变换一次 
			count = 0;
		}
	}
	
#elif VERSION == 2 // 中断方式
	EA = 1;
	ET0 = 1;
	TR0 = 1;
	while(1);
#endif
}

#if VERSION == 2 // T0中断
void int_T0(void) interrupt 1 using 0
{
	TH0 = 0x3c;
	TL0 = 0xb0;
	count++;
	if (count == 20)
	{
		P2_7 = !P2_7;
		count = 0;
	}
}

#endif

电路图:

编译:

仿真:

(2)05-2直流电机调速:

利用定时器产生 pwm 波对电机进行调速。单片机p2.7口用于驱动直流电机,开机时电机不转。当按下button复位开关S1(接P3.7口)、S2(接P3.6口)、S3(接P3.5口),风扇分别以1档(占空比50%)、2档(占空比80%)、3档(占空比100%)的速度转动;按下S4(接P3.4口)电机停止转动,档位为0。其中要求使用定时器T0产生周期为2ms的连续脉冲信号。

要求高低电平转换在定时器中断里产生。

代码:

#include <reg51.h>

typedef unsigned char uchar;

sbit work = P2^7; // 连接点击/示波器的引脚

uchar times = 0, count = 0, pwm = 0, max = 250, key, it;

void main(void)
{
	work = 0;
	TMOD = 0x02; 	// 方式2
	TH0 = 6; 		// 每次0.25us 记录4次即为1ms, 周期为2ms
	TL0 = 6;
	EA = 1;
	ET0 = 1;
	TR0 = 1;
	while (1)
	{
		key = P3 >> 4;
		switch (key)
		{
			case 14:
				for (it = 0; it < 255; it++); 		// 去抖
				if (key == P3 >> 4) pwm = 0; 		// 关闭
				break;
			case 13:
				for (it = 0; it < 255; it++); 		// 去抖
				if (key == P3 >> 4) pwm = 250; 		// 3档
				break;
			case 11:
				for (it = 0; it < 255; it++); 		// 去抖
				if (key == P3 >> 4) pwm = 200; 		// 2档
				break;
			case 7:
				for (it = 0; it < 255; it++); 		// 去抖
				if (key == P3 >> 4) pwm = 125; 		// 1档
		}
	}
}

void int_T0(void) interrupt 1 				// T0计时器中断
{
	if (++times == 4) 						// 每1ms执行一次 周期为2ms
	{
		times = 0;
		if (++count < pwm) work = 1; 		// 在工作占比中
		else if (count < max) work = 0; 	// 没在工作占比中
		else count = 0; 					// 一轮结束
	}
}


电路图:

编译:

仿真:

电路板-单片机实体:

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
定时器/计数器是嵌入式系统中常用的模块,可以用来实现计时、延时、PWM输出等功能。下面介绍一些常见的定时器/计数器的定时实验。 1. 延时实验 使用定时器/计数器实现延时功能,一般是通过设置定时器/计数器的初值和计数模式来实现的。以 8051 单片机定时器为例,可以使用以下代码实现延时 1 秒: ```c #include <reg51.h> void delay() { TMOD = 0x01; // 设置定时器0为模式1,使用定时器模式 TH0 = 0x3C; // 设置定时器初值,定时1s TL0 = 0xAF; TR0 = 1; // 启动定时器 while(TF0 == 0); // 等待定时器溢出 TR0 = 0; // 停止定时器 TF0 = 0; // 清除溢出标志 } void main() { while(1) { P1 = 0x55; // P1口输出0x55 delay(); // 延时1s P1 = 0xAA; // P1口输出0xAA delay(); // 延时1s } } ``` 2. 计时实验 使用定时器/计数器实现计时功能,一般是通过设置定时器/计数器的时钟源和计数模式来实现的。以 AVR 单片机定时器为例,可以使用以下代码实现计时 1 秒: ```c #include <avr/io.h> #include <avr/interrupt.h> volatile uint32_t timer_count = 0; // 计时器计数值 ISR(TIMER1_COMPA_vect) // 定时器1比较匹配中断服务程序 { timer_count++; // 计数器加1 } int main() { DDRB = 0xFF; // PB口设置为输出 TCCR1A = 0x00; // 定时器1模式设置为普通计数模式 TCCR1B = 0x0D; // 定时器1时钟源设置为外部时钟,分频系数为1024 OCR1A = 15624; // 定时器1比较值,计数1s TIMSK1 = (1 << OCIE1A); // 允许定时器1比较匹配中断 sei(); // 开启全局中断 while(1) { if(timer_count >= 1000) // 如果计时器计数值达到1s { PORTB = ~PORTB; // PB口翻转 timer_count = 0; // 计数器清零 } } return 0; } ``` 3. PWM输出实验 使用定时器/计数器实现 PWM 输出功能,可以通过设置定时器/计数器的时钟源、计数模式和比较匹配值来实现。以 STM32 单片机定时器为例,可以使用以下代码实现 PWM 输出: ```c #include "stm32f10x.h" int main() { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // 定时器分频系数为72 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = 1000 - 1; // 定时器计数值为1000 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 500 - 1; // 比较匹配值为500 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM2, &TIM_OCInitStructure); TIM_Cmd(TIM2, ENABLE); while(1); return 0; } ``` 以上是一些常见的定时器/计数器的定时实验,可以根据自己的需要进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leisure_水中鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值