第七届蓝桥杯单片机省赛题目

首先读题可知我们需要初始化led,数码管,ds18b20模块,pwm也就是定时器模块,

代码如下:

数码管的

#include "smg.h"


uchar code t_display[]={                       //标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x00,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

uchar code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码
//共阳给7低电平亮,给6高电平亮
void smg_display(uchar wei,duan,dian)
{
	P0 = 0xff;
	hc573(7);
	P0 = 0x01<<wei;
	hc573(6);
	if(!dian) P0 = ~t_display[duan];
	else P0 = ~(t_display[duan]|0x80);
	hc573(7);
	Delay_1ms(1);
}

按键的:

#include "key.h"
uchar key_count = 0;
//p30 p31 p32 p33
//s7  s6  s5  s4
uchar key_had(void)//这里加个标志位否则反复进来
{
	if(key_count==1 && (P30==0||P31==0||P32==0||P33==0))
	{
		key_count = 0;
		Delay_1ms(50);
		if(P30==0)return 7;
		if(P31==0)return 6;
		if(P32==0)return 5;
		if(P33==0)return 4;
	}
	else if(P30==1&&P31==1&&P32==1&&P33==1)
	{
		key_count = 1;
	}
	return 0;
}

温度模块:

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台
  日    期: 2011-8-9
*/

#include "onewire.h"

//单总线延时函数
void Delay_OneWire(unsigned int t)
{
	t = t*12;
  while(t--);
}

//DS18B20芯片初始化
bit Init_DS18B20(void)
{
	bit initflag = 0;
	DQ = 1;
	Delay_OneWire(12);
	DQ = 0;
	Delay_OneWire(80); 
	DQ = 1;
	Delay_OneWire(10); 
	initflag = DQ;    
	Delay_OneWire(5);
  
	return initflag;
}

//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);
}

//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}
unsigned int ds18b20(uchar dot)
{
	uchar templ,temph;
	uint temp;
	Init_DS18B20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	
	Init_DS18B20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	
	templ = Read_DS18B20();
	temph = Read_DS18B20();
	temp = (temph<<8)|templ;
	switch(dot)
	{
		case 0:temp = temp * 0.0625;break;
		case 1:temp = temp * 0.625;break;
		case 2:temp = temp * 6.25;break;
	}
	return temp;
}

定时器:

#include "timer.h"
uint miao=50;
//1KHZ->1/1000的频率,T等于1/1000的时间所以是0.1ms因为频率是1ms而要改pwm波所以定时0.1ms然后计数10次
uchar count = 0;
uint count1 = 1000;
void Timer0_Isr(void) interrupt 1
{
	count++;
	if(count==10)count=0;
}

void Timer0_Init(void)		//1毫秒@12.000MHz
{
	AUXR &= 0x7F;			//定时器时钟12T模式
	TMOD &= 0xF0;			//设置定时器模式
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0 = 1;				//使能定时器0中断
	EA = 1;
}

void pwm_control(uchar num)
{
	
	if(count<=num)
	{
		P34 = 1;
	}
	else
	{
		P34 = 0;
	}
}

void Timer1_Isr(void) interrupt 3
{
	count1--;
	if(count1==0)
	{
		miao--;count1=1000;
	}
	
}

void Timer1_Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x40;			//定时器时钟1T模式
	TMOD &= 0x0F;			//设置定时器模式
	TL1 = 0x20;				//设置定时初始值
	TH1 = 0xD1;				//设置定时初始值
	TF1 = 0;				//清除TF1标志
	TR1 = 1;				//定时器1开始计时
	ET1 = 1;				//使能定时器1中断
}

定时器这里需要注意题目要求信号频率1Khz,所以我们的周期为1ms,而要输出pwm那就需要给定周期,我们在0.1ms的定时器基础上去计数来形成pwm波,那么输出的pwm周期为1ms。

最终代码在文章最后

我们需要制作两个数码管界面一个是电机pwm输出另一个是显示温度的界面,其次是S7按键去切换两个模式,如果直接判断那就会出现切换不了因为切换到另一个模式后S7还是按下的状态会切换回去,所以我们在函数外去定义一个标志位,用标志位去切换两个模式,其他的没有什么难度了。

主程序代码:

#include "STC15.h"
#include "sys.h"
#include "smg.h"
#include "key.h"
#include "timer.h"
#include "onewire.h"
uchar S6=0;S7=0,S45=1;
uchar pattern=1;
extern uint miao;
uchar num=0,num_old=1;
uint tem=0;
void smg_pwm(void)
{
	if(num_old%2==1)
	{
		smg_display(0,17,0);
		smg_display(1,pattern,0);
		smg_display(2,17,0);
		smg_display(3,18,0);
		smg_display(4,miao/1000,0);
		smg_display(5,miao%1000/100,0);
		smg_display(6,miao%100/10,0);
		smg_display(7,miao%10,0);
		if(num==4)
		{
			pattern++;if(pattern==4)pattern=1;
		}
		if(num==5)
		{
			miao+=60;
		}
		if(num==6)
		{
			miao=0;
			
		}
		
		if(pattern==1)
		{
			pwm_control(2);
			if(miao!=0)
			{
				P0=0xfe;
				hc573(4);
			}
		}
		if(pattern==2)
		{
			pwm_control(3);
			if(miao!=0)
			{
				P0=0xfd;
				hc573(4);
			}

		}
		if(pattern==3)
		{
			pwm_control(7);
			if(miao!=0)
			{
				P0=0xfb;
				hc573(4);
			}
		}
		if(miao==0)
		{
			EA=0;
			P0=0xff;
			hc573(4);
			
		}
		else EA=1;
	}
}
void S7_cufa(void)
{
	if(num_old%2==0)
	{
		
		tem = ds18b20(0);
		smg_display(0,17,0);
		smg_display(1,4,0);
		smg_display(2,17,0);
		smg_display(3,18,0);
		smg_display(4,18,0);
		smg_display(5,tem/10,1);
		smg_display(6,tem%10,1);
		smg_display(7,12,0);	
		
		
	}

}

void main(void)
{
	
	
	sysinit();
	
	Timer0_Init();
	Timer1_Init();
	while(1)
	{
		num = key_had();
		smg_pwm();
		S7_cufa();
		if(num==7)
		{
			num_old++;
		}
//		tem = ds18b20(0);
//		smg_display(0,tem/10,1);
//		smg_display(1,tem%10,1);
		//P34 = 1;
	}
}

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值