蓝桥杯CT107D 单片机编程例题

一、按键

#include "stc15f2k60s2.h"
#define InitHC138(n) 	{P2 = P2 & 0x1f | (n << 5);}
#define u8				unsigned char
#define u32				unsigned int

bit key_flag;	// 按键标志位
u8 key;			// 按键状态

u8 Key4_Read(void)    //独立按键扫描函数,读取键值
{
    u32 Key_temp;
	u8 Key_Value;
	
	P3 |= 0x0f;
	Key_temp = P3&0x0f;
	
	switch(Key_temp)
	{
	    case 0x0e : Key_Value = 7; break;  //S7
		case 0x0d : Key_Value = 6; break;  //S6
		case 0x0b : Key_Value = 5; break;  //S5
		case 0x07 : Key_Value = 4; break;  //S4
		default: Key_Value = 0;
	}
	return Key_Value;
}

u8 Key16_Read(void)    //矩阵按键扫描函数,读取键值
{
    u32  Key_temp;
	u8 Key_Value;
	
	//按键扫描的识别部分
	P44=0; P42=1; P35=1; P34=1; P3|=0X0F; //第一列拉低,其余全为高
	Key_temp = P3;                        //读取P3低四位I/O状态
	
	P44=1; P42=0; P35=1; P34=1; P3|=0X0F;  //第二列拉低,其余全为高
	Key_temp = (Key_temp<<4) | (P3&0X0F);  //读取P3低四位I/O状态
	
	P44=1; P42=1; P35=0; P34=1; P3|=0X0F; //第三列拉低,其余全为高
	Key_temp = (Key_temp<<4) | (P3&0X0F); //读取P3低四位I/O状态
	
	P44=1; P42=1; P35=1; P34=0; P3|=0X0F; //第四列拉低,其余全为高
	Key_temp = (Key_temp<<4) | (P3&0X0F);  //读取P3低四位I/O状态
	
	//有按键按下Key_temp相应位为0	
	
	//按键扫描的编码部分
	switch(~Key_temp)   
	{
		case 0X8000: Key_Value = 4; break;   //S4
		case 0X4000: Key_Value = 5; break;   //S5
		case 0X2000: Key_Value = 6; break;   //S6
		case 0X1000: Key_Value = 7; break;   //S7
		
		case 0X0800: Key_Value = 8; break;   //S8
		case 0X0400: Key_Value = 9; break;   //S9
		case 0X0200: Key_Value = 10; break;   //S10
		case 0X0100: Key_Value = 11; break;   //S11
		
		case 0X0080: Key_Value = 12; break;   //S12
		case 0X0040: Key_Value = 13; break;   //S13
		case 0X0020: Key_Value = 14; break;   //S14
		case 0X0010: Key_Value = 15; break;   //S15
		
		case 0X0008: Key_Value = 16; break;   //S16
		case 0X0004: Key_Value = 17; break;   //S17
		case 0X0002: Key_Value = 18; break;   //S18
		case 0X0001: Key_Value = 19; break;   //S19
		
		default: Key_Value = 0;  //无按键按下
	}
	return Key_Value;
}

void Key_config()
{
	while(key_flag)
	{
		key_flag = 0;
		key = Key4_Read();
		switch(key)
		{
			case 7:
				InitHC138(4);
				P0 = 0xfe;	P2 = 0x00;
				break;
			case 6:
				InitHC138(4);
				P0 = 0xff;	P2 = 0x00;
				break;
		}
	}
}

void Timer1Init(void)		//1毫秒@12.000MHz
{
    AUXR &= 0xBF;					//定时器时钟12T模式
    TMOD &= 0x0F;					//设置定时器模式
    TH1 = (65535 - 1000) / 256;		//设置定时初始值
    TL1 = (65535 - 1000) % 256;		//设置定时初始值
    TF1 = 0;						//清除TF1标志
    TR1 = 1;						//定时器1开始计时

    ET1 = 1;
    EA  = 1;
}

void main()
{
    InitHC138(4);
    P0 = 0xff;	P2 = 0x00;
    InitHC138(5);
    P0 = 0x00;	P2 = 0x00;

	Timer1Init();
    while(1)
    {
		Key_config();
    }
}


void Serv_T1()	interrupt 3
{
	u32 i;
    TH1 = (65535 - 1000) / 256;		//设置定时初始值
    TL1 = (65535 - 1000) % 256;		//设置定时初始值
	
	i++;
	if(i == 10)
	{
		i = 0;
		key_flag = 1;
	}
}

二、外部中断

#include "stc15f2k60s2.h"
#define InitHC138(n) 	{P2 = P2 & 0x1f | (n << 5);}
sbit led1 = P0^0;
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S4 = P3^3;
void Delay_ms(unsigned int t)
{
	unsigned char i, j;
	while(t--)
	{
		i = 12;
		j = 169;
		do
		{
			while (--j);
		} while (--i);
	}
}


void Init_key()
{
	if(!S7)
	{
		Delay_ms(15);
		if(!S7)
		{	
			S4 = 0;
		}
		while(!S7);
	}
	if(!S6)
	{
		Delay_ms(15);
		if(!S6)
		{	
			S4 = 1;
		}
		while(!S6);
	}
}
void Init_inter0()
{
	IT1 = 0;	// 低电平触发,触发之后必须是高电平变为低电平才会触发
//  IT1 = 1;	// 跳变沿触发	
	EX1 = 1;	// 打开 INT0 的中断允许
	EA  = 1;	// 打开总中断
}

void Servive_0()	interrupt 2		// 外部中断1
{
	InitHC138(4);
	led1 = ~led1;
}

void main (void)
{
	InitHC138(5);
	P0 = 0x00;	P2 = 0x00;
	InitHC138(4);
	P0 = 0xff;	P2 = 0x00;
	
	Init_inter0();
	while (1)
	{
		Init_key();
	}
}

三、 定时器

#include "stc15f2k60s2.h"
#define InitHC138(n) 	{P2 = P2 & 0x1f | (n << 5);}
sbit led1 = P0^0;
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S4 = P3^3;


void Init_Timer_0()
{
	TMOD |= 0x01;	// 选择定时器0,工作方式1,仅用TR0打开启动
	
	TH0 = (65536 - 1000) / 256;		// 定时1ms
	TL0 = (65536 - 1000) % 256;
	
	ET0 = 1;		// 打开定时器0中断允许
	EA  = 1;		// 打开总中断
	TR0 = 1;		// 打开定时器
}

unsigned int count = 0;
void Timer0()	interrupt 1
{
	count++;
	if(count == 500)	// count == 500 既是经过500ms
	{
		count = 0;
		InitHC138(4);
		led1 = ~led1;
		P2 = 0x00;
	}
	// 一定要记得重载
	TH0 = (65536 - 1000) / 256;
	TL0 = (65536 - 1000) % 256;
}

  
void main (void)
{
	InitHC138(5);
	P0 = 0x00;	P2 = 0x00;
	InitHC138(4);
	P0 = 0xff;	P2 = 0x00;
	
	Init_Timer_0();
	while (1)
	{
		// CPU不参与定时器的运行
	}
}

定时器2实现数码刷新

// ds1302实现电子钟
#include "STC15F2K60S2.h"
#include "ds1302.h"
#define InitHC138(n)	{P2 = P2 & 0x1f | (n << 5);}
#define u8 				unsigned char
#define	u32 			unsigned int

// 段码
code u8 tab[]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xff, 0xbf};
u8 Buf[8];		// 数码管的显示缓冲区
u8 Timer[7] = {0x24,0x59,0x23,0x03,0x03,0x03,0x20};

void DS1302_config()
{
	u8 i;
	u8 Write = 0x80;
	Write_Ds1302_Byte(0x8e, 0x00);		// 关闭保护,可以写入
	for(i = 0; i < 7; i++)
	{
		Write_Ds1302_Byte(Write, Timer[i]);
		Write += 2;
	}
	Write_Ds1302_Byte(0x8e, 0x80);		// 恢复保护,拒绝写入
}

void Read_ds1320_time()
{
	u8 i;
	u8 Read = 0x81;
	for(i = 0; i < 7; i++)
	{
		Timer[i] = Read_Ds1302_Byte(Read);
		Read += 2;
	}
}

// 数码管显示端口配置
void Display_SMG(u8 pos, u8 dat)
{
	InitHC138(7);
	P0 = 0xff;			P2 = 0x00;
	InitHC138(6);
	P0 = 0x01 << pos;	P2 = 0x00; 
	InitHC138(7);
	P0 = dat;			P2 = 0x00;
}


// 定时器2配置 1ms
void Timer2Init(void)	//1毫秒@12.000MHz
{
	AUXR &= 0xFB;		//定时器时钟12T模式
	T2L = 0x18;			//设置定时初始值
	T2H = 0xFC;			//设置定时初始值
	AUXR |= 0x10;		//定时器2开始计时
	IE2 |= 0x04;		// 使能中断
	EA  = 1;
}

// 定时器2中断
void T0_Servive()	interrupt 12
{
	u8 pos;
	T2L = 0x18;		//设置定时初始值
	T2H = 0xFC;		//设置定时初始值

	Display_SMG(pos, Buf[pos]);		// 1ms刷新一个数码管,即每隔8ms刷新一次
	if(++pos == 8)	pos = 0;		// 通过移位来实现动态显示
}

// 数码管显示数据的配置函数
void smgdatset(u8 d0,u8 d1,u8 d2,u8 d3,
			   u8 d4,u8 d5,u8 d6,u8 d7)
{
	Buf[0]=d0;
	Buf[1]=d1;
	Buf[2]=d2;
	Buf[3]=d3;
	Buf[4]=d4;
	Buf[5]=d5;
	Buf[6]=d6;
	Buf[7]=d7;
}

void Show_time()
{
	Read_ds1320_time();
	// 显示时间
	smgdatset(tab[Timer[2]/16], tab[Timer[2]%16], tab[11], 
			  tab[Timer[1]/16], tab[Timer[1]%16], tab[11], 
			  tab[Timer[0]/16], tab[Timer[0]%16]);
}

int main(void)
{
	InitHC138(4);
	P0 = 0xff;	P2 = 0x00;
	InitHC138(5);
	P0 = 0x00;	P2 = 0x00; 

	Timer2Init();
	DS1302_config();
	while(1)
	{
		Show_time();
	}
}

四、串口通讯

#include "stc15f2k60s2.h"
#define InitHC138(n) 	{P2 = P2 & 0x1f | (n << 5);}
sbit led1 = P0^0;
void UartInit(void)		//115200bps@11.0592MHz
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x40;		//定时器1时钟为Fosc,即1T
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设定定时器1为16位自动重装方式
	TL1 = 0xE8;		//设定定时初值
	TH1 = 0xFF;		//设定定时初值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}

void uart() interrupt 4  //串口通信中断服务函数
{
	if(RI)
	{
		RI=0;
	}
	
	if(TI)
	{
		TI=0;
	}	
}

void uart_sendchar(unsigned char ch)	// 发送字符函数
{
	SBUF=ch;
	while(!TI);
	TI=0;
}

//void uart_sendstr(unsigned char *str)	// 发送字符串函数
//{
//	while(*str)
//		uart_sendchar(*str++);
//}

unsigned char uart_recechar()
{
	unsigned char dat;
	while(!RI);
	RI = 0;
	dat = SBUF;
	return dat;
}


void main (void)
{
	char i;
	InitHC138(5);
	P0 = 0x00;	P2 = 0x00;
	InitHC138(4);
	P0 = 0xff;	P2 = 0x00;
	
	UartInit();
	while (1)
	{
		i = uart_recechar();
		if(i == 'a')
		{
			InitHC138(4);	led1 = ~led1;	P2 = 0x00;
			uart_sendchar(i);
		}
	}
}

在串口通讯情况下重映射调用 printf( ) 函数

#include "STC15F2K60S2.H"
#include "stdio.h"

void Delay_ms(unsigned int t)
{
	unsigned char i, j;
	while(t--)
	{
		i = 12;
		j = 169;
		do
		{
			while (--j);
		} while (--i);
	}
}

void UartInit(void)        //9600bps@11.0592MHz
{
	SCON = 0x50;               
	AUXR |= 0x40;               
	AUXR &= 0xFE;               
	TMOD &= 0x0F;               
	TL1 = 0xE0;               
	TH1 = 0xFE;               
	ET1 = 0;               
	TR1 = 1;
	TI=1;               	//调用printf函数一定要令TI = 1 
}
void main()
{
	float i =3.14159;
	UartInit();
	while(1)
	{
		printf("hello world\r\n");
		printf("%.5f\n", i);
		Delay_ms(1000);
	}
}

在串口通信情况下用 sancf() 函数

#include "STC15F2K60S2.H"
#include "stdio.h"
#define InitHC138(n)	{P2 = P2 & 0x1f | (n << 5);}

void UartInit(void)                //9600bps@11.0592MHz
{
	SCON = 0x50;               
	AUXR |= 0x40;               
	AUXR &= 0xFE;               
	TMOD &= 0x0F;               
	TL1 = 0xE0;               
	TH1 = 0xFE;               
	ET1 = 0;               
	TR1 = 1; 
	TI  = 1;		// printf()
	RI  = 1;		// scanf()
}
void main()
{
	char i =0;
	
	InitHC138(5);
	P0 = 0x00; P2 = 0x00;
	InitHC138(4);
	P0 = 0xff; P2 = 0x00;
	
	UartInit();
	
	while(1)
	{
		scanf("%c", &i);
		printf("%c\n", i);
		if(i == 'a')
		{
			InitHC138(4);
			P00 = ~P00;
			P2 = 0x00;
		}
	}
}

五、DS18B20 温度测量

#include <stc15f2k60s2.h>
#include "onewire.h"	 // 官方底层驱动代码
#define InitHC138(n)	{P2 = P2 & 0x1f | (n << 5);}
#define uint 	unsigned int
#define uchar	unsigned char
unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; 
long  wendu;

void Delay_ms(uint t)
{
	unsigned char i, j;
	while(t--)
	{
		i = 12;
		j = 169;
		do
		{
			while (--j);
		} while (--i);
	}
}

void Display_SMG(uchar pos, uchar dat)
{
	InitHC138(7);
	P0 = 0xff;	P2 = 0x00;
	InitHC138(6);
	P0 = 0x01 << pos;	P2 = 0x00;
	InitHC138(7);
	P0 = dat;
}

long read18b20()
{
    unsigned char low,high;
    long temp;
    
    init_ds18b20();
    Write_DS18B20(0xcc);
    Write_DS18B20(0x44);
    Delay_OneWire(200);
    
    init_ds18b20();
    Write_DS18B20(0xcc);
    Write_DS18B20(0xbe);
    low = Read_DS18B20();
    high = Read_DS18B20();
    
    temp = ((high&0x0f)<<8)|(low);
    temp *= 6.25;
    
//    temp=high&0x0f;
//    temp=temp<<8;
//    temp=temp|low;
//    temp=temp*6.25;
    
    return temp;
}

void Show_SMG()
{
	wendu = read18b20();	// 保留两位小数
	Display_SMG(4, tab[wendu / 1000]);
	Delay_ms(2);
	Display_SMG(5, tab[wendu / 100 % 10]&0x7f);		// 添加小数点
	Delay_ms(2);
	Display_SMG(6, tab[wendu / 10 % 10]);
	Delay_ms(2);
	Display_SMG(7, tab[wendu % 10]);
	Delay_ms(2);
}

void main()
{
    InitHC138(4);
	P0 = 0xff;	P2 = 0x00;
	InitHC138(5);
	P0 = 0x00;	P2 = 0x00;
   
    while(1)
    {
		Show_SMG();
    }
    
}

六、电子钟

#include "stc15f2k60s2.h"
#include "ds1302.h"		// 官方底层驱动代码
#define InitHC138(n)	{P2 = P2 & 0x1f | (n << 5);}
// 数码管
code unsigned char SMGNoDot_CA[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
code unsigned char SMGDot_CA[10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};

unsigned char Write_DS1302_adrr[7] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
unsigned char Read_DS1302_adrr[7] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
// 21年3月3日, 周六, 23点59分24秒

unsigned char Timer[7] = {0x24,0x59,0x23,0x03,0x03,0x03,0x20};//BCD码    十六进制中的数字等效十进制的数字
//                        24秒 59分 23时  3号  3月 星期三  20年  
 

void DelaySMG(unsigned char t)
{
	while(t--);
}

void DisplaySMG_Bit(unsigned char pos, unsigned char dat)
{
	InitHC138(7);
	P0 = 0xff;	P2 = 0x00;
	InitHC138(6);
	P0 = 0x01 << pos;	P2 = 0x00;
	InitHC138(7);
	P0 = dat;	P2 = 0x00;
}


void DS1302_Config()  //读取当前时间
{
	char i;
	Write_Ds1302_Byte(0x8e,0x00); 	  //关闭保护,可以写入  
	for( i = 0; i < 7; i++)
	{
		Write_Ds1302_Byte(Write_DS1302_adrr[i],Timer[i] );
	}
	Write_Ds1302_Byte(0x8e,0x80);     //恢复保护,拒绝写入
}

void Read_DS1302_Timer()     //读取不用保护,写入需要保护
{
	char i;
	
	for(i = 0; i < 7; i++)
	{
		Timer[i] = Read_Ds1302_Byte( Read_DS1302_adrr[i] );
	}
}


void Display_DS1302()
{
	//时
	DisplaySMG_Bit(0, SMGNoDot_CA[Timer[2] / 16]);
	DelaySMG(100);
	DisplaySMG_Bit(1, SMGNoDot_CA[Timer[2] % 16]);
	DelaySMG(100);
	
	DisplaySMG_Bit(2,0xbf);
	DelaySMG(100);
	
	//分
	DisplaySMG_Bit(3, SMGNoDot_CA[Timer[1] / 16]);
	DelaySMG(100);
	DisplaySMG_Bit(4, SMGNoDot_CA[Timer[1] % 16]);
	DelaySMG(100);

	DisplaySMG_Bit(5,0xbf);
	DelaySMG(100);
	
	//秒
	DisplaySMG_Bit(6, SMGNoDot_CA[Timer[0] / 16]);
	DelaySMG(100);
	DisplaySMG_Bit(7, SMGNoDot_CA[Timer[0] % 16]);
	DelaySMG(100);


	// 关闭所有数码管
	InitHC138(6);
	P0 = 0xff;	P2 = 0x00;
	InitHC138(7);
	P0 = 0xff;	P2 = 0x00;
}

void main()
{
	InitHC138(4);
	P0 = 0xff;	P2 = 0x00;
	InitHC138(5);
	P0 = 0x00;	P2 = 0x00;
	
	DS1302_Config();
	while(1)
	{
		Read_DS1302_Timer();
		Display_DS1302();
	}
}

七、超声波

#include "stc15f2k60s2.h"
#include "intrins.h"
#define InitHC138(n)	{P2 = P2 & 0x1f | (n << 5);}
#define uint  unsigned int
#define uchar unsigned char
#define nop()	{_nop_();_nop_();_nop_();_nop_();_nop_();\
				 _nop_();_nop_();_nop_();_nop_();_nop_();}

sbit TX = P1^0;		// 发送引脚
sbit RX = P1^1;		// 接收引脚

code uchar tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
uchar dspbuf[8] = {10,10,10,10,10,10,10,10};
uchar dspcom = 0;

uint count = 0;
bit flag;
uint t = 0;

void Send_ult()
{
	uchar i = 16;	   // 发送8个脉冲
	// 起始信号
	TX = 0;
	for (i = 0; i < 16; i++)
	{
		TX = ~TX;
		nop();nop();nop();nop();nop();
		nop();nop();nop();nop();nop();
	}
}

// 显示函数
void Display()
{
	InitHC138(7);
	P0 = 0xff;					P2 = 0x00;
	InitHC138(6);
	P0 = (1 << dspcom);			P2 = 0x00;
	InitHC138(7);
	P0 = tab[dspbuf[dspcom]];	P2 = 0x00;
	
	if(++dspcom == 8)
	{
		dspcom = 0;
	}
}

uint distance = 0;
void Init_time()
{
	TMOD |= 0x11;	// 配置定时器工作模式
	TH0 = (65536 - 2000) / 256;    // 定时2毫秒
	TL0 = (65536 - 2000) % 256;
	TH1 = 0;	// 计数		
	TL1 = 0;
	
	EA  = 1;	// 打开总开关
	ET0 = 1;	// 打开定时器0中断
	TR0 = 1;	// 启动定时器0
}

void Servie_time()	interrupt 1		// 定时器0中断
{
	TH0 = (65536 - 2000) / 256;
	TL0 = (65536 - 2000) % 256;
	Display();	// 每2毫秒数码管刷新一次
	if(++count == 200)	// 400 毫秒发送一次
	{
		flag = 1;
		count = 0;
	}
}

void Config_ult()
{
	// 200 毫秒刷新一次
	if(flag)
	{
		flag = 0;
		Send_ult();		// 发送方波信号
		TR1 = 1;		// 开始计时
		while((RX == 1) && (TF1 == 0));		// 等待收到脉冲
		TR1 = 0;		// 结束计时
		
		// 如果发生溢出
		if(TF1 == 1)
		{
			TF1 = 0;
			distance = 9999;	// 无返回
		}
		else
		{
			distance = (uint) (TH1 << 8) | TL1;
			distance *= 0.017 * 1.085;		// 单位 cm  (1.085 为误差补偿)
		}
		TH1 = 0;	// 重新从零开始计时
		TL1 = 0;
	}
	
	// 数据处理
	dspbuf[5] = distance / 100;
	dspbuf[6] = distance % 100 / 10;
	dspbuf[7] = distance % 10;
}

void main()
{
	InitHC138(4);
	P0 = 0xff;	P2 = 0x00;
	InitHC138(5);
	P0 = 0x00;  P2 = 0x00;
	
	Init_time();
	while(1)
	{
		Config_ult();
	}
}	

八、EEPROM 存储器

/*******************************************************************************  
* 文件名称:开机次数存储实验,按下复位按键,或重新上电,数码管显示+1
* 实验目的:1.掌握I2C总线通讯基本特点和工作时序
*           2.掌握51单片机模拟I2C总线时序的程序设计方法
*           3.掌握EEPROM存储器的特性及AT24C02的读写操作方法
* 			4.存储开机次数
* 硬件环境:IAP15F2K61S2@11.0592MHz
*******************************************************************************/
#include "stc15f2k60s2.h"
#include "iic.h"		// 官方提供的底层驱动
#include "intrins.h"
#define InitHC138(n)	{P2 = P2 & 0x1f | (n << 5);}
#define uchar unsigned char
#define uint unsigned int

code uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//定义段码数组
uchar boot_time = 0;	// 存放开机次数

void Delay_ms(uint t)		//@11.0592MHz
{
	unsigned char i, j;
	while(t--)
	{
		_nop_();
		_nop_();
		_nop_();
		i = 11;
		j = 190;
		do
		{
			while (--j);
		} while (--i);		
	}
}

// *******************自添加部分***************************

void write_eeprom(unsigned char add,unsigned char date)
{
	IIC_Start();//启动总线
	IIC_SendByte(0xa0);//发送设备地址,第八位为0所以为写
	IIC_WaitAck();//等待应答
	IIC_SendByte(add);//发送数据地址
	IIC_WaitAck();//等待应答
	IIC_SendByte(date);//发送数据
	IIC_WaitAck();//等待应答
	IIC_Stop();//停止总线
}

unsigned char read_eeprom(unsigned char add)
{
	unsigned char temp;//定义变量temp用来获得eeprom中的数据
	EA = 0;//关闭中断,中断可能会影响总线时序
	IIC_Start();//开启总线
	IIC_SendByte(0xa0);
	//发送设备地址,第八位为0所以为写,因为读取的时候为读取现在的地址加一,所以要发送现在写的地址进去
	IIC_WaitAck();//等待应答
	IIC_SendByte(add);//发送数据地址
	IIC_WaitAck();//等待应答

	IIC_Start();//开启总线
	IIC_SendByte(0xa1);//发送设备地址,第八位为1所以为读,读取的地址为刚刚我们写入的地址
	IIC_WaitAck();//等待应答
	temp = IIC_RecByte();//读取数据
	IIC_WaitAck();//等待应答
	IIC_Stop();//停止总线
	EA = 1;//打开中断
	return temp;//返回temp
}

//************************************************************

void Display_SMG(uint pos, uint dat)
{
	InitHC138(7);
	P0 = 0xff;			P2 = 0x00;
	InitHC138(6);
	P0 = 0x01 << pos;	P2 = 0x00;
	InitHC138(7);
	P0 = dat;			P2 = 0x00;
}

void Show_SMG()
{
	Display_SMG(6, tab[boot_time / 10]);
	Delay_ms(10);
	Display_SMG(7, tab[boot_time % 10]);
	Delay_ms(10);
}

void main()
{
	InitHC138(4);
	P2 = 0xff;	P2 = 0x00;
	InitHC138(5);
	P2 = 0x00;	P2 = 0x00;
	
	boot_time = read_eeprom(0x01);
	write_eeprom(0x01,++boot_time);
	while(1)
	{
		Show_SMG();
	}
}

九、PCF8591_ADC实验

/*******************************************************************************  
* 文件名称:ADC转换实验
* 实验目的:1.掌握I2C总线通讯基本特点和工作时序
*           2.掌握51单片机模拟I2C总线时序的程序设计方法
*           3.掌握PCF8591 ADC芯片的操作方法
* 程序说明:1.使用程序前在 Preprocessor Symbols 中增加宏定义ADC_PCF8591
*           2.调节电位器Rb2,观察数码管显示情况
* 硬件环境:IAP15F2K61S2@11.0592MHz
*******************************************************************************/
#include "stc15f2k60s2.h"  //定义51单片机特殊功能寄存器
#include "iic.h"    //I2C总线驱动库 
#include "intrins.h"
#define InitHC138(n)	{P2 = P2 & 0x1f | (n << 5);}
#define uint			unsigned int
#define uchar			unsigned char

code unsigned char tab[] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char count_t;
unsigned int ADC = 0;
unsigned char Bit = 0;
void Delay_ms(unsigned int t)		//@11.0592MHz
{
	unsigned char i, j;
	while(t--)
	{
		_nop_();
		_nop_();
		_nop_();
		i = 11;
		j = 190;
		do
		{
			while (--j);
		} while (--i);		
	}
}

void Display_SMG(uchar pos, uchar dat)
{
	InitHC138(7);
	P0 = 0xff;	P2 = 0x00;
	InitHC138(6);
	P0 = 0x01 << pos;	P2 = 0x00;
	InitHC138(7);
	P0 = dat;	P2 = 0x00;
}

unsigned int ADC_PCF8591(unsigned char ch)
{
	unsigned int dat;
	
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x40+ch);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	
	dat = IIC_RecByte();
	IIC_SendAck(1);        //不应答
	IIC_Stop();
	return dat;
}

void Init_T0()
{
	// 定时 1ms 
	AUXR |= 0x80;		// 定时器时钟1T模式
	TMOD &= 0xF0;		// 设置定时器模式
	TL0   = 0xCD;			// 设置定时初值
	TH0   = 0xD4;			// 设置定时初值
	TF0   = 0;			// 清除TF0标志
	TR0   = 1;			// 定时器0开始计时
	ET0   = 1;			// 打开定时器0中断
	EA    = 1;
}

//定时器中断服务函数
void Servive_T0(void)  interrupt 1  //默认中断优先级 1
{

    if(++count_t == 50)	// 50 ms 获取一次
	{
		count_t = 0;
		Bit = 1;		// 用标志位,防止卡死
	} 
}

void Show_SMG()
{
	if(Bit == 1)
	{
		Bit = 0;
		ADC = ADC_PCF8591(0x01);	// 0x01 光敏电阻调节  0x03 R2电位器调节
	}
	Display_SMG(5, tab[ADC / 100]);
	Delay_ms(2);
	Display_SMG(6, tab[ADC / 10 % 10]);
	Delay_ms(2);
	Display_SMG(7, tab[ADC % 10]);
	Delay_ms(2);
}

//主函数
void main(void)
{ 
	InitHC138(4);
	P0 = 0xff;	P2 = 0x00;
	InitHC138(5);
	P0 = 0x00;	P2 = 0x00;
	
	
	Init_T0();
	// PCF8591初始化  
	// Init_PCF8591(0x03);  // 0x01 光敏电阻调节  0x03 R2电位器调节
    while(1)
    {
		Show_SMG();
    }
}

十、PCF8591_DAC实验

/*******************************************************************************  
* 文件名称:DAC转换实验
* 实验目的:1.掌握I2C总线通讯基本特点和工作时序
*           2.掌握51单片机模拟I2C总线时序的程序设计方法
*           3.掌握PCF8591 DAC操作方法
* 程序说明:1.使用程序前增加宏定义DAC_PCF8591
*           2.通过按键S1、S5控制PCF8591芯片输出模拟电压值,使用万用表测量排针J3
              的D/A引脚,与数码管显示数值进行比对,并尝试分析误差的产生原因。
			3.数码管显示电压值单位为毫伏(mV)
* 硬件说明:IAP15F2K61S2@11.0592MHz
*******************************************************************************/

#include "stc15f2k60s2.h"  //定义51单片机特殊功能寄存器
#include "iic.h"    //I2C总线驱动库
#include "intrins.h"
#define uint 	unsigned int
#define uchar	unsigned char
#define InitHC138(n)	{P2 = P2 & 0x1f | (n << 5);}
#define VREF  5200  //PCF8591参考电压
sbit S7 = P3^0;
sbit S6 = P3^1;
unsigned char dac_value;  //DAC转换数据
unsigned int Vaout;  //输出电压

code unsigned char tab[] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

void Delay_ms(unsigned int t)		//@11.0592MHz
{
	unsigned char i, j;
	while(t--)
	{
		_nop_();
		_nop_();
		_nop_();
		i = 11;
		j = 190;
		do
		{
			while (--j);
		} while (--i);		
	}
}

void Display_SMG(uchar pos, uchar dat)
{
	InitHC138(7);
	P0 = 0xff; P2 = 0x00;
	InitHC138(6);
	P0 = 0x01 << pos;	P2 = 0x00;
	InitHC138(7);
	P0 = dat;	P2 = 0x00;
}


void PCF8591_DAC(unsigned char dat)
{
	IIC_Start();
	IIC_SendByte(0x90);		// 地址+写
	IIC_WaitAck();
	IIC_SendByte(0x40);		// DAC输出模式
	IIC_WaitAck();
	
	IIC_SendByte(dat);		// DAC写入模式
	IIC_WaitAck();
	IIC_Stop();
}

void Scanf_key()
{
	if(S7 == 0)
	{
		dac_value+=50;
		PCF8591_DAC(dac_value);
		while(!S7);
	}
	if(S6 == 0)
	{
		dac_value-=50;
		PCF8591_DAC(dac_value);
		while(!S6);
	}
}

void Show_SMG()
{
	Vaout = VREF/255*dac_value;
	
	Display_SMG(4, tab[Vaout / 1000]);
	Delay_ms(2);
	Display_SMG(5, tab[Vaout / 100 % 10]);
	Delay_ms(2);
	Display_SMG(6, tab[Vaout / 10 % 10]);
	Delay_ms(2);
	Display_SMG(7, tab[Vaout % 10]);
	Delay_ms(2);
}

//主函数
void main(void)
{ 
	InitHC138(4);
	P0 = 0xff; P2 = 0x00;
	InitHC138(5);
	P0 = 0x00; P2 = 0x00;

    while(1)
    {
		Scanf_key();
		Show_SMG();
    }
}

十一、NE555频率

#include "STC15F2K60S2.h"
#define InitHC138(n, dat)	{P0 = dat; P2 = P2 & 0x1f | (n << 5); P2 &= 0x1f;}
#define u8 					unsigned char
#define u32					unsigned int
	
code u8 tab[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
u8 buf[8];
u32 freq;

void Display_SMG(u8 pos, u8 dat)
{
	InitHC138(7, 0xff);
	InitHC138(6, 0x01 << pos);
	InitHC138(7, dat);
}

void SMG_set(u8 d0, u8 d1, u8 d2, u8 d3,
			 u8 d4, u8 d5, u8 d6, u8 d7)
{
	buf[0] = d0;
	buf[1] = d1;
	buf[2] = d2;
	buf[3] = d3;
	buf[4] = d4;
	buf[5] = d5;
	buf[6] = d6;
	buf[7] = d7;
}

void Init_Fre()
{
	TMOD = 0x15;	// T1:定时器 T0:计数器
	TH0 = TL0 = 0;  // 计数清零
	TL1 = 0x18;		//设置定时初始值
	TH1 = 0xFC;		//设置定时初始值
	
	TR0 = TR1 = 1;
	ET1 = 1;
	EA = 1;
}

void timer() interrupt 3
{
	u32 count;
	TL1 = 0x18;		//设置定时初始值
	TH1 = 0xFC;		//设置定时初始值
	if (++count == 1000)
	{
		count = 0;
		TR0 = 0;
		freq = (u32) (TH0 << 8) | TL0;
		TL0 = TH0 = 0;
		TR0 = 1;
	}
}


void Timer2Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x04;		//定时器时钟1T模式
	T2L = 0xCD;		//设置定时初始值
	T2H = 0xD4;		//设置定时初始值
	AUXR |= 0x10;		//定时器2开始计时
	
	IE2 |= 0x04;
	EA  = 1;
}

void Ser_T2(void)	interrupt 12
{
	u8 pos;
	T2L = 0xCD;		//设置定时初始值
	T2H = 0xD4;		//设置定时初始值
	
	Display_SMG(pos, buf[pos]);
	if(++pos == 8)
		pos = 0;
}

void Show_fre(void)
{
	SMG_set(0xff, 0xff, 0xff,
			tab[freq/10000%10], tab[freq/1000%10], tab[freq/100%10], tab[freq/10%10], tab[freq%10]);
}
void main()
{
	InitHC138(4, 0xff);
	InitHC138(5, 0x00);
	
	Init_Fre();
	Timer2Init();
	while(1)
	{
		Show_fre();
	}
}

十二、PWM输出

/*51单片机PWM输出程序模板
本程序通过定时器控制使引脚模拟输出PWM
通过控制定时器1,使引脚P0^0输出PWM,void Out_Pwm(u16 value)函数是封装好的PWM输出函数,用户通过
在主函数中调用此函数,改变value值即可改变占空比输出PWM信号value取值范围(0~1000)  */


#include "stc15f2k60s2.h"    
#define InitHC138(n)	{P2 = P2 & 0x1f | (n << 5);}
typedef unsigned int u16;	 
typedef unsigned char u8;

sbit PWM = P0^0;
u16 count;
u16 i;


void Timer1Init()
{
	TMOD|=0X10;//选择为定时器1模式,工作方式1,仅用TR1打开启动。
	TH1 = 0xFF; 
	TL1 = 0xff;   //1us	
	ET1=1;//打开定时器1中断允许
	EA=1;//打开总中断
	TR1=1;//打开定时器			
}

void Time1(void) interrupt 3    //3 为定时器1的中断号  1 定时器0的中断号 0 外部中断1 2 外部中断2  4 串口中断
{
	TH1 = 0xFF; 
	TL1 = 0xff;   //1us
	count++; 
}

void Out_Pwm(u16 value)
{
	if(count>1000)  //PWM周期为1000*1us
	{
		count=0;
	}
	if(count <value)	
	{
		InitHC138(4);
		PWM=1;	P2 = 0x00;
	}
	else
	{
		InitHC138(4);
		PWM=0;	P2 = 0x00;
	}	
}

void main()
{
	Timer1Init();
	while(1)
	{
		Out_Pwm(900);	// 输出占比90%为高电平的方波		
	}		
}

呼吸灯

#include <stc15f2k60s2.h>
bit flag_pwn;
unsigned char led_dat;
void Timer0Init()		//10us@12.000MHz
{
		AUXR |= 0x80;		
		TMOD &= 0xF0;	
		TL0 = 0x88;		
		TH0 = 0xFF;		
		TF0 = 0;		
		TR0 = 1;		
		ET0 = 1;
		EA = 1;
}	
void ShowLed(unsigned char led_dat)
{
		P2 = P2&0x1f|0x80;
		P0 = led_dat;
		P2 = P2&0x1f;
}

void T0_time() interrupt 1
{
		static unsigned int count = 0,n = 0,pwn = 0;
		TL0 = 0x88;		
		TH0 = 0xFF;	
		if(++count >= 1000)  //周期10ms
		{
				count = 0;
		}
		if(++n >= 100)     //每隔1ms变化一次pwn
		{
				n = 0;
				if(flag_pwn == 0)   
				{
						pwn++;                 //PWN增加,灯泡由亮到暗
						if(pwn == 1000)
						{
								flag_pwn = 1;
						}					
				}
				else if(flag_pwn == 1)
				{
						pwn--;                //PWN减少,灯泡由暗到亮
						if(pwn == 0)
						{
								flag_pwn = 0;
						}
				}
		}
		
		if(count > pwn)        //亮
		{
				ShowLed(0xfe);
		}
		else                   //暗
		{
				ShowLed(0xff);
		}		
}

void CloseFucker()
{
		P2 = P2&0x1f|0xa0;
		P0 = 0xaf;
		P2 = P2&0x1f;
}

void main()
{
		CloseFucker();
		Timer0Init();
		while(1)
		{
			;
		}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值