STC8h1k28六个基本实验

实验一 STC8h1k28 熟悉开发环境及端口输出控制

实验内容:
项目1:
参考原理图,设计1位闪烁灯程序,每次亮、灭时长均为500ms。
项目2:
参考原理图,设计三色流转灯程序,GRB三种颜色的LED轮番点亮,每次只亮一盏,每次点亮时长为500ms。

原理图:
在这里插入图片描述
实验原理:
(共阳)LED负极接单片机IO口(P00\P01\P02),当IO口输出低电平时LED被点亮,反之熄灭。

/*程序代码及注释:
项目1:
参考原理图,设计1位闪烁灯程序,每次亮、灭时长均为500ms。代码如下:*/
#include <stc8h.h>
/*存储的是定义好的寄存器地址。*/
#include<intrins.h>/*用到_nop_()这个函数就得包含这个头文件里面有关于这个函数的定义*/
void Delay500ms()		//@11.0592MHz延时函数
{
    
    
	unsigned char i, j, k;

	_nop_();//用到它就要用到这个头文件<intrins.h>
	_nop_();
	i = 22;
	j = 3;
	k = 227;
	do
	{
    
    
		do
		{
    
    
			while (--k);
		} while (--j);
	} while (--i);
}
void initialize()//初始化io口工作模式
{
    
    
	P0M1 &=0xf8; //设置P0口低三位为准双向口模式。
	P0M0 &=0xf8;//设置P0口低三位为准双向口模式。
//设置IO口工作模式00(共阳),设置P00,P01,P02为准双向口模式(既可以输出也可//以输入)
//01推挽输出(共阴),10高祖输入(A/D转换时),11开漏输出(电平匹配时)
}

void LED()
{
    
    
		P00=0;//因为是共阳LED所以给低电平它亮,给高电平它灭
		Delay500ms();//延时500ms再灭,不能太快灭和亮,不然人眼看不出变化
		P00=1;//灭灯//或以上两行用它代替P00!=P00;
		Delay500ms();
}
 
void main()//万年不变三段式:初始化,循环体,循环内容
{
    
    
		initialize();//初始化用到哪个io口就先设置工作模式
		while(1)
		{
    
    
			LED();//放大循环里让灯不停运转
		}
}
/*项目2:
参考原理图,设计三色流转灯程序,GRB三种颜色的LED轮番点亮,每次只亮一盏,每次点亮时长为500ms。代码如下:*/
#include <stc8h.h>
/*存储的是定义好的寄存器地址。*/
#include<intrins.h>//用到_nop_()这个函数就得包含这个头文件里面有关于这个函数的定义
//用尖括号是用于包含标准库的头文件
//双引号一般用于包含用户自己编写的头文件
char i;//控制灯轮转的变量
void Delay500ms()		//@11.0592MHz延时函数
{
    
    
	unsigned char i, j, k;
	_nop_();//用到它就要用到这个头文件<intrins.h>
	_nop_();
	i = 22;
	j = 3;
	k = 227;
	do
	{
    
    
		do
		{
    
    
			while (--k);
		} while (--j);
	} while (--i);
}
void initialize()//IO口工作模式初始化
{
    
    
	P0M1 &=0xf8;
	P0M0 &=0xf8;/*设置IO口工作模式00(共阳),设置P00,P01,P02为准双向口模式(既可以输//出也可以输入)*/
	//01推挽输出(共阴),10高祖输入(adc),11开漏输出
}
void LED()//LED轮转函数
{
    
    
	for(i=0;i<3;i++)
	{
    
    
		P0=~(1<<i);//利用i变量进行左移位,每次1移动i位后取反,电平为0的那一位
//亮,也就是先蓝灯亮500ms再红灯亮500ms再绿灯亮500ms
		Delay500ms();
	}
	i=0;//当i等于3时,也就是完成一轮亮灯(蓝红绿)i清零
}


void main()
{
    
    
	initialize();//初始化用到哪个io口就先设置工作模式
	while(1)
	{
    
    
		LED();//放大循环里让灯不停运转
	}
}


实验二 STC8h1k28基于定时器的LED控制

实验内容:
项目1:
利用定时器产生周期为100ms的方波,并以此方波控制LED以相同频率闪烁(使用查询方式实现);
项目2:
利用定时器控制流水灯流转时间,每盏灯每次点亮时长500ms(使用中断方式实现)。
原理图:在这里插入图片描述

实验原理:
(共阳)LED负极连接单片机IO口(P00\P01\P02).当IO口输出低电平时LED被点亮,反之熄灭。
定时/计数器工作原理
定时器定时时间计算公式(16bit):
在这里插入图片描述

/*程序代码及注释:
项目1:
利用定时器产生周期为100ms的方波,并以此方波控制LED以相同频率闪烁(使用查询方式实现);代码如下:*/
#include <stc8h.h>
/*存储的是定义好的寄存器地址*/
void Timer0Init (void)    //50毫秒延时@11.0592MHz
{
    
    
 	AUXR &= 0x7F;    //定时器时钟12T模式
	/*T0x12=0定时计数脉冲与传统8051单片机的计数脉冲完去全一样
	计数脉冲周期位系统周期的12倍,即12分频;当=1,与系统周期一致,即无分频。*/
TMOD &= 0xF0;    /*设置定时器模式,设置定时器0,GATE=0,TR0=1/0可直接通过软件设置定时器开关,当它等于1时不仅通过软件设置TR0开关还有引脚P32 P33参与,C/T非=0的定时器模式=1计数器模式,M1=0M0=0,16位自动重装初始值*/
 	TL0 = 0xB0;   //设置定时初值低8位
 	TH0 = 0x3C;   //设置定时初值高8位
 	TF0= 0;   //清空溢出标志位
 	TR0= 1;   //开启定时器0 
}
void initialize()//初始化IO口模式
{
    
    
	P0M1 &=0xf8; //P0低三位IO设置为准双向口模式
	P0M0 &=0xf8;// P0低三位IO设置为准双向口模式
//设置IO口工作模式00(共阳),设置P00,P01,P02为准双向口模式(既可以输出也可以输入)
	//01推挽输出(共阴),10高祖输入(adc),11开漏输出
}
void LED()//查询方式实现灯以相同频率闪烁函数
{
    
    
	if(TF0)//判断是否到50ms
	{
    
    
		TF0=0;//到50ms进入if,后清零
		P00=~P00;//控制灯的亮灭
	}
}
void main()//万年不变主函数三段式:初始化,循环体,循环内容
{
    
    
	initialize();//初始化定时器
	Timer0Init ();//初始化io口
	P0=0xff;//初始化P00先灭灯
	while(1)
	{
    
    
		LED();//放大循环里让灯循环运转
	}
}
/*项目2:
利用定时器控制流水灯流转时间,每盏灯每次点亮时长500ms(使用中断方式实现)。代码如下:*/
#include <stc8h.h>
/*存储的是定义好的寄存器地址。*/
char i,j=0;//j为满50ms加一,加满10次满500ms,flag=1,j=0。I是控制灯移位变量。
bit flag;//500ms标志变量
void Timer0Init (void)    //50毫秒@11.0592MHz
{
    
    
 	AUXR &= 0x7F;    //定时器时钟12T模式
	/*T0x12=0定时计数脉冲与传统8051单片机的计数脉冲完去全一样
	计数脉冲周期位系统周期的12倍,即12分频;当=1,与系统周期一致,即无分频。*/
 	TMOD &= 0xF0;    /*设置定时器模式,设置定时器0,GATE=0,TR0=1/0可直接通过软件设置定时器开关,当它等于1时不仅通过软件设置TR0开关还有引脚P32 P33参与,C/T非=0的定时器模式=1计数器模式,M1=0M0=0,16位自动重装初始值*/
 	TL0 = 0xB0;   //设置定时初值低8位
 	TH0 = 0x3C;   //设置定时初值高8位
 	TF0= 0;   //清除TF0标志
 	TR0= 1;   //定时器0开始计时
}
void initialize()
{
    
    
	P0M1 &=0xf8; //P0低三位准双向口模式
	P0M0 &=0xf8;// P0低三位准双向口模式
//设置IO口工作模式00(共阳),设置P00,P01,P02为准双向口模式(既可以输出也可以输入)
	//01推挽输出(共阴),10高祖输入(adc),11开漏输出
	EA=1;
	ET0=1;
}
void ET0_LED() interrupt 1
{
    
    
	j++;//每50ms加一
	if(j==10)//满500ms进入
	{
    
    
		j=0;//清零保证下一个500ms正常定时
		flag=1;//自己定义的标志位,等于一代表500ms到了
	}
}
void LED()//LED轮转函数
{
    
    
	if(flag)//只有500ms到了才能进入流水的运转
	{
    
    
		flag=0;//清零保证下一次500ms正常进行亮灯不然你会看到混彩灯
		P0=~(1<<i);//用i实现位移控制轮流500ms亮灯
		i++;//在之前基础上位移到下一位
		if(i>2)
		{
    
    
			i=0;//蓝红绿进行一轮后i清零保证下一轮亮灯正常进行
		}
		
	}
}
void main()
{
    
    
	initialize();//初始化定时器
	Timer0Init ();//初始化io口
	while(1)
	{
    
    
		LED();//放大循环里让流水灯运转
	}
}
 


实验三 STC8h1k28中断、查询与按键控制

实验内容:
项目1:
每次按下按键,流水灯变化一种颜色,三种颜色循环变化,按键不按时颜色不变。(用外部中断实现)。
项目2:
每次按下按键,流水灯变化一种颜色,三种颜色循环变化,按键不按时颜色不变。
(用普通查询实现)。
项目3:
每次按下按键,流水灯变化一种颜色,三种颜色循环变化,按键不按时颜色不变。
(用定时器中断查询实现)。
原理图:
在这里插入图片描述
在这里插入图片描述
实验原理:
(共阳)LED负极接单片机IO口(P00\P01\P02),当IO口输出低电平时LED被点亮,反之熄灭。
按键按下为低电平,扫描按键为低电平灯亮。
定时/计数器工作原理
定时器定时时间计算公式(16bit):

在这里插入图片描述

/*程序代码及注释:
项目1:
每次按下按键,流水灯变化一种颜色,三种颜色循环变化,按键不按时颜色不变。(用外部中断实现)。*/

//外部中断实现流水灯运转
#include <stc8h.h>
#define  KEY1 P32//预处理,还没开始前把下面出现过的KEY1用P32代替
#define  KEY2 P33//预处理,还没开始前把下面出现过的KEY2用P33代替
bit key_flag=0;//自定义按键一标志位先清零,按键按下置1
unsigned char i;//控制灯移位变量
void setup()//外部中断0和io口初始化变量
{
    
    
	EA=1;//打开总中断
	EX0=1;//外部中断0中断允许位,它打开等会才能进入中断服务子函数
	EX1=1;//外部中断1中断允许位,它打开等会才能进入中断服务子函数
	IE0=0;//外部中断0中断请求标志位,它等于1进入中断服务子函数
	IE1=0;//外部中断1中断请求标志位,它等于1进入中断服务子函数
	IT0=1;//外部中断0下降沿触发,就是按键按下才触发,抬起不触发
	IT1=1;//外部中断1下降沿触发,就是按键按下才触发,抬起不触发
	P0M1 &=0xf8;//设置P0口低三位为准双向口模式
	P0M0 &=0xf8;//设置P0口低三位为准双向口模式
	P0 &=0xff;//先把灯都灭了;
}
void INT0_IE0() interrupt 0//外部中断0的中断服务子函数
{
    
    
	key_flag=1;//自定义按键一标志位,按键按下置1
	while(!KEY1);//等待按键抬起
}
void INT0_IE1() interrupt 2//外部中断1的中断服务子函数
{
    
    
	key_flag=1;//自定义按键一标志位,按键按下置1
	while(!KEY2);//等待按键抬起
}
void LED_turn()//led流转函数
{
    
    
	if(key_flag)//确认按键按下才进入亮灯
	{
    
    
		key_flag=0;//自定义按键一标志位清零
		P0=~(1<<i);//按键按下一次亮一种灯
		i++;//移位量比前一次多一
		if(i>2)//灯循环一次后i清零
			i=0;
	}
}

void loop()//循环题里面的内容
{
    
    
	LED_turn();//调用led流转函数
}
void main()//万年不变主函数三段式
{
    
    
	setup();//初始化
	while(1)//循环体
	{
    
    
		loop();//亮灯程序
	}
}

/*项目2:
每次按下按键,流水灯变化一种颜色,三种颜色循环变化,按键不按时颜色不变。
(用普通查询实现)。*/

//普通查询按键流转灯
#include <stc8h.h>
#include <intrins.h>//用到 _nop_()就要这个头文件
#define  KEY1 P32//预处理,还没开始前把下面出现过的KEY1用P32代替
#define KEY2 P33//预处理,还没开始前把下面出现过的KEY1用P33代替
bit key_flag=0;//自定义按键一标志位先清零,按键按下置1
unsigned char i;//控制灯移位变量
void Delay20ms()  //@11.0592MHz
{
    
    
 unsigned char i, j, k;

 _nop_();
 _nop_();
 i = 1;
 j = 216;
 k = 35;
 do
 {
    
    
  do
  {
    
    
   while (--k);
  } while (--j);
 } while (--i);
}

void setup()//外部中断0和io口初始化变量
{
    
    
 	P0M1 &=0xf8;//设置P0口低三位为准双向口模式
 	P0M0 &=0xf8;//设置P0口低三位为准双向口模式
 P0 &=0xff;//先把灯都灭了;
}
void key_see_about()//按键查询,看按键1或二是否按下
{
    
    
 	if(KEY1==0)//如果按键1按下
 	{
    
    
  		Delay20ms();//延时20ms按键1消抖环节
  		if(KEY1==0)//按键1还是低电平则标志为置1,以上为按键1消抖环节
  		{
    
    
  	 		key_flag=1;//按键标志位置1
  		}
 	} 
 	if(KEY2==0)//如果按键2按下
 	{
    
    
  		Delay20ms();//延时20ms
  		if(KEY2==0)//以上为按键2消抖环节
  		{
    
    
   			key_flag=1;//标志位置1
  		}
 	}
}
void LED_turn()//led流转函数
{
    
    
 	if(key_flag)//确认按键按下才进入亮灯
 	{
    
    
  		key_flag=0;//自定义按键一标志位清零
  		P0=~(1<<i);//按键按下一次亮一种灯
  		i++;//移位量笔前一次多一
  		if(i>2)//灯循环一次后i清零
    			i=0;
 	}
}

void loop()//循环题里面的内容
{
    
    
key_see_about();
 	LED_turn();//调用led流转函数
}
void main()
{
    
    
 	setup();//初始化
 while(1)//循环体
 	{
    
    
  		loop();//亮灯程序
 	}
}
/*项目3:
每次按下按键,流水灯变化一种颜色,三种颜色循环变化,按键不按时颜色不变。
(用定时器中断查询实现)。*/
//定时器查询按键流转灯
#include <stc8h.h>//头文件包含下面部分需要用到的语句定义
#define KEY1 P32//预处理,还没开始前把下面出现过的KEY1用P32代替
#define KEY2 P33//预处理,还没开始前把下面出现过的KEY2用P33代替
bit flag=0;//按键标志位,为1表示按键被按下
unsigned char I;//控制灯颜色转变的移位自定义变量
void time0_setup()//定时器一初始化
{
    
    
	TMOD &=0xf0;//定时器模式tr0=1启动定时器,工作方式0
	AUXR &=0x7f;//定时器0为12分频
	TL0=0xb0;//设置定时器初值
	TH0=0x3c;//设置定时器初值
	TR0=1;//启动定时器0
	TF0=0;//中断请求标志为清零
}
void setup()//初始化io空口和中断
{
    
    
	P0M1 &=0xf8;//设置为p00-p02为准双向口
	P0M0 &=0xf8;//设置为p00-p02为准双向口
	EA=1;//打开总中断开关
	ET0=1;//打开中断允许位
}
void et0_time0() interrupt 1//定时器0中断服务子函数
{
    
    
	if(KEY1==0||KEY2==0)
		flag=1;//按键按下标志变量置1
}
void led_turn()
{
    
    
	if(flag)
	{
    
    
		flag=0;//标志变量清零
		P0=~(1<<I);//灯变化下一种颜色
		I++;//移位变量加一
		if(I>2)//灯三种颜色循环一次就移位变量清零,方便下次灯循环
			I=0;
	}
}
void loop()//循环体里面包含的内容
{
    
    
	led_turn();
}
void main()//万年不变主函数三段式
{
    
    
	time0_setup();//定时器0初始化
	setup();//io口,中断初始化,即要用到的东西都先初始化设置一次
	while(1)//循环体
	{
    
    
		loop();
	}
} 


实验四 STC8h1k28数码管秒表程序设计

实验内容:
项目:

采用数码管、按键和内部定时实现秒计时功能,最大计时9999秒,超时9999秒则计数清零。外部按键KEY1控制秒表启停,按键KEY2清零秒表计时。
原理图:在这里插入图片描述
在这里插入图片描述
实验原理:
数码管显示和动态扫描
按键按下为低电平,扫描按键为低电平灯亮。
(共阳)数码管负极接单片机IO口,当IO口输出低电平时对应段选或位选被点亮,反之熄灭。

//程序代码及注释:
#include <stc8h.h>
#include<intrins.h>//用到_nop_();
#define font_PORT P2//段选
#define position_PORT P1//位选
sbit key1=P3^2;//sbit定义一个引脚,sfr定义一个并行口
sbit key2=P3^3;
typedef unsigned char uchar;
typedef unsigned int uint;

uchar code LED_SMG[]={
    
    0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};//字形码控制//段选
uchar code Scan_bit[]={
    
    0xfe,0xfd,0xfb,0xf7};//控制位选
uchar data Dis_buf[]={
    
    0,10,10,10};//控制显示内容
uint moment = 0;//ms变量
uint second = 0;//s变量
bit start = 1;
void Delay20ms()		//@12.000MHz
{
    
    
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 1;
	j = 234;
	k = 113;
	do
	{
    
    
		do
		{
    
    
			while (--k);
		} while (--j);
	} while (--i);
}
void Timer0Init(void)//1000微秒@12.000MHz(定时器0,16位自动重装12t模式12.000MHz)
{
    
    
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}void Display_Init()//初始化中断、IO口
{
    
    
	P2M1 = 0;//P2口设置为准双向口
	P2M0 = 0; //P2口设置为准双向口
	P1M1 &=0xF0; //P1口低4位设置为准双向口
	P1M0 &=0xF0; //P1口低4位设置为准双向口
	EA=1;//打开总中断
	ET0=1;//打开定时器0中断允许位
	TimerOInit();//初始化定时器0
}
void Dis_figure(unsigned int dd)
{
    
    
	if(dd<10)
	{
    
    
		Dis_buf[0] = dd;//右边第一个数码管亮的数字
		Dis_buf[1] = 10; //左边第三个数码管不亮
		Dis_buf[2] = 10; //左边第二个数码管不亮
		Dis_buf[3] = 10; //左边第一个数码管不亮
	}
	else if(10<=dd<100)
	{
    
    
		Dis_buf[0] = dd%10; //右边第一个数码管亮的数字
		Dis_buf[1] = dd/10%10; //右边第二个数码管亮的数字
		Dis_buf[2] = 10; //左边第二个数码管不亮
		Dis_buf[3] = 10; //左边第一个数码管不亮
	}
	else if(100<=dd<1000)
	{
    
    
		Dis_buf[0] = dd%10; //右边第一个数码管亮的数字
		Dis_buf[1] = dd/10%10; //右边第二个数码管亮的数字
		Dis_buf[2] = dd/100%10; //右边第三个数码管亮的数字
		Dis_buf[3] = 10; //左边第一个数码管不亮
	}
	else if(1000<=dd<9999)
	{
    
    
		Dis_buf[0] = dd%10; //右边第一个数码管亮的数字
		Dis_buf[1] = dd/10%10; //右边第二个数码管亮的数字
		Dis_buf[2] = dd/100%10; //右边第三个数码管亮的数字
		Dis_buf[3] = dd/1000%10; //右边第四个数码管亮的数字
	}
}
void dis_second()//每1ms进一次
{
    
    
	if(start)
		moment++;//每1毫秒加一
	if(moment == 1000)//满一秒进入
	{
    
    
		moment = 0;//满1000ms清零
		second++;//加一秒变量
		Dis_figure(second);//数码管显示
	}
}
void T0_Int() interrupt 1//定时器0外部中断服务子函数
{
    
    
	static uchar i;//控制数码管对应段选位选亮的变量
	position_PORT = 0xff;//先把数码管灭了,消影
	font_PORT = LED_SMG[Dis_buf[i]];//数码管管段选亮字形码
	position_PORT = Scan_bit[3-i];//控制位选亮
	i++;
	if(i>3)
		i=0;//以上两行保证数码动态显示
	dis_second();//数码管显示
}
void INT0() interrupt 0//外部中断0中断服务子函数
{
    
    
	Delay20ms();
	if(!key1)//按键消抖
		start = !start;//每按一次取标志位取非一次,控制启停
}
void INT1() interrupt 2//外部中断1中断服务子函数
{
    
    
	second = 0;//计时清零
	Dis_buf[0] = 0;//数码管清零
}
void setup()
{
    
    
	EA=1;//打开中断总开关
	IT0=1;//外部中断0下降沿触发,=0上升沿下降沿都触发
	EX0=1;//外部中断0中断允许位打开
	IT1=1; //外部中断1下降沿触发
	EX1=1; //外部中断1中断允许位打开
	Display_Init();
}
void main(void)//万年不变主函数,三段式
{
    
    
	setup();//初始化
	while(1);//循环体,啥也不执行在这耗时,保证个定时器功能瞬时间流逝时执行
}
 


实验五 STC8h1k28单片机与 PC 串口通信

实验内容:
项目:

PC 机通过串口调试助手发送字符指令给单片机。单片机接到指令后,按照指令点亮或熄灭对应的 LED,并将指令回传给 PC 机,并在串口调试助手的接收缓冲区显示出来。指令对照表如下:
R——红灯亮; G——绿灯亮; B——蓝灯亮; A——所有灯亮; O——所有灯灭。
实验原理:
1.单片机与PC机间采用电平转换模块连接, 实现单片机串口与PC机USB接口的物理连接和电平转换。单片机与PC之间采用异步串口通信。 波特率9600, 信息格式为8个数据位, 1个停止位,无奇偶校验位。 PC机可采用STC-ISP软件内嵌的“串口调试助手”进行调试。
2.波特率计算公式
在这里插入图片描述

3.STC-ISP 在线编程工具中内嵌的串口助手。在这里插入图片描述
原理图:
在这里插入图片描述

//程序代码及注释:
#include<stc8h.h>
char s_data='x';//初始化变量
void UartInit(void)		//[email protected]
{
    
    
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x40;		//定时器1时钟为Fosc,即1T
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设定定时器1为16位自动重装方式
	TL1 = 0xE0;		//设定定时初值
	TH1 = 0xFE;		//设定定时初值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}
void UART_R(void) interrupt 4 using 1//串口1中断服务子函数
{
    
    
 if(RI)//接受成功时进入if
 {
    
    
s_data = SBUF;//接收数据,CPU从SBUF读数据
  	RI =0;//接受成功清零标志位,保证下次接收
 	 switch(s_data)
{
    
    
case 'b'://发送‘b’蓝灯亮
P00=0;
break; //跳出整个循环
case 'r': //发送‘r’红灯亮
P01=0;
break; //跳出整个循环
case 'g': //发送‘g’绿灯亮
P02=0;
break; //跳出整个循环
case 'o': //发送‘o’灯不亮
P0=0xff;
break; //跳出整个循环
case 'a': //发送‘a’灯都亮
P0=0;	
break; //跳出整个循环
default: //除了以上情况外,
SBUF = 'n'; //发送数据‘n’。CPU向SBUF写入数据
while(!TI); //等待发送成功
break;//跳出整个循环
}
	 	SBUF =s_data ; //发送数据。CPU向SBUF写入数据
   		while(!TI);//等待发送成功
}
if(TI)//发送成功进入if
	TI=0;//发送标志位清零
}
 void setup()
 {
    
    
  	P0M1 &=0xF8;//(P0M1=0x00)//P0低三位设置为准双向口模式
P0M0 &=0XF8;//(P0M0=0x00)//P0低三位设置为准双向口模式
  	ES=1;//打开串口1中断允许控制位
	EA=1; //打开总中断

 }
void main(void)//万年不变主函数三段式
{
    
    
	setup();//初始化函数
	UartInit();初始化串口1
	while(1);//耗时
}
 


实验六 STC8h1k28基于 ADC 的模拟按键识别与控制

实验内容:
项目:

将模拟按键键值通过串口发送至 PC 机的串口调试助手, 并通过四个模拟按键控制评估版上的发光二极管亮灭。 控制方式如下: 1 键按下蓝灯亮, 2 键按下红灯亮, 3 键按下绿灯亮,
4 键按下三种颜色的灯均亮, 没有按键按下时所有灯均熄灭。
原理图:
在这里插入图片描述
在这里插入图片描述
实验原理:
按下不同模拟按键模拟通道口得到不同模拟数值,ADC转换成对应数值给cpu,在通过switc—case循环选择控制灯亮灭;
(共阳)LED 负极连接单片机 IO 口(P00\P01\P02), 当 IO 口输出低电平时 LED 被点亮,反之
熄灭;
PC 机的串口调试助手。

//程序代码及注释:

#include <stc8h.h>
#include<intrins.h>//用到了_nop_();
#define uchar unsigned char 
#define uint unsigned int
#define ulong unsigned long


uchar adc_data;//读取结果高八位放于此变量 

void Delay20ms()		//@24.000MHz
{
    
    
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 2;
	j = 211;
	k = 231;
	do
	{
    
    
		do
		{
    
    
			while (--k);
		} while (--j);
	} while (--i);
}

void UartInit(void)		//[email protected]
{
    
    
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x40;		//定时器1时钟为Fosc,即1T
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设定定时器1为16位自动重装方式
	TL1 = 0xE0;		//设定定时初值
	TH1 = 0xFE;		//设定定时初值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}


void adc_init()
{
    
    
	ADC_CONTR |=1<<7;//打开ADC 电源 
 } 
 
 uint adc_read()
 {
    
    
 	uint adc_value; //存放ADC转换结果高八位的自定义变量
 	ADC_CONTR &=(0xf0);//清除ADC_CHS[3:0] 
	ADC_CONTR |=7;//设置ADC模拟通道选择P1.7 
	
	P1M1 |=0x80;//P1.7高阻输入 
	P1M0 &=0x7f;//P1.7高阻输入 
	ADC_CONTR |=0x40;//启动ADC转换 
	while(!ADC_CONTR & 0x20);//等待转换成功 
	ADC_CONTR &=~0x20;//清零完成标志位 
	adc_value = ADC_RES;//ADC转换结果高八位给变量 
	ADC_RES=0;//高八位寄存器清零 
	ADC_RESL = 0;//低八位寄存器清零 
	return adc_value; //返还高八位值,返回值必须与函数类型一致 
 }
 
 void UART_R(void) interrupt 4 using 1
 {
    
    
 	if(TI)//发送成功则进入if 
 		TI = 0;//发送成功,ti清零 
 }
 void adc_uart()
 {
    
    
 	SBUF = adc_data;//发送数据。CPU向SBUF写入数据 
 	Delay20ms();//延时20ms 
}
 void adc_led()//按下不同模拟键得到不同ADC转换值,亮相应灯 
 {
    
    
 	switch(adc_data)
 	{
    
    
 		case 0:		P00 = 0;	break;//转换数值高八位为0,亮蓝灯 
 		case 0x2A:		P01 = 0;	break;//转换数值高八位为2a,亮红灯 
 		case 0x51:		P02 = 0;	break;//转换数值高八位为51,亮绿灯 
 		case 0x7F:		P0 &= 0xF8;	break;//转换数值高八位为7f,亮混彩灯 
 		default:		P0 |= 0x07;	break;//转换数值高八位除了以上情况,灯灭 
 		
	 }
 }
void main()//万年不变主函数三段式
{
    
    
	EA=1;//打开中断总开关 
	ES=1;//打开串口1中断允许控制位
	adc_init();//初始化ADC 
	UartInit();//初始化串口1 
	P0M1 &=0xf8;//设置P0低三位为准双向 
	P0M0 &=0xf8;//设置P0低三位为准双向 
	while(1)
	{
    
    
		adc_data = adc_read();//读dac转换值取出高八位转换值 
		adc_uart();//发送数据。CPU向SBUF写入数据 函数 
		adc_led();//ADC值控制亮灯函数 
	}
}
 
 

猜你喜欢

转载自blog.csdn.net/m0_53126906/article/details/125711105