STC8h1k28 six basic experiments

Experiment 1 STC8h1k28 Familiar with the development environment and port output control

Experiment content:
Project 1:
Refer to the schematic diagram to design a 1-bit flashing light program, with each on and off time being 500ms.
Project 2:
Referring to the schematic diagram, design a three-color rotating light program. The LEDs of the three colors of GRB will be turned on in turn, and only one light will be turned on at a time. The lighting time of each time is 500ms.

Schematic diagram:
Insert image description here
Experimental principle:
(common anode) LED negative pole is connected to the IO port of the microcontroller (P00\P01\P02), when the IO port outputs a low level, the LED is lit, otherwise it is off.

/*程序代码及注释:
项目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();//放大循环里让灯不停运转
	}
}


Experiment 2 STC8h1k28 timer-based LED control

Experiment content:
Project 1:
Use a timer to generate a square wave with a period of 100ms, and use this square wave to control the LED to flash at the same frequency (implemented using query mode); Project
2:
Use a timer to control the flow time of the running water lamp, each lamp Each lighting time is 500ms (implemented by interrupt method).
Schematic:Insert image description here

Experimental principle:
 (Common anode) The cathode of the LED is connected to the IO port of the microcontroller (P00\P01\P02). When the IO port outputs low level, the LED is lit, and vice versa.
Timer/counter working principle
Timer timing time calculation formula (16bit):
Insert image description here

/*程序代码及注释:
项目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();//放大循环里让流水灯运转
	}
}
 


Experiment 3 STC8h1k28 interrupt, query and key control

Experiment content:
Project 1:
Each time the button is pressed, the running water lamp changes one color, and the three colors change in a cycle. The color does not change when the button is not pressed. (Achieved using external interrupts).
Project 2:
Each time the button is pressed, the running water lamp changes one color, and the three colors change cyclically. The color remains unchanged when the button is not pressed.
(Achieved using ordinary queries).
Project 3:
Each time the button is pressed, the running water lamp changes one color, and the three colors change cyclically. The color remains unchanged when the button is not pressed.
(Using timer interrupt query to achieve).
Principle diagram:
Insert image description here
Insert image description here
Experimental principle:
 (Common anode) The cathode of the LED is connected to the IO port of the microcontroller (P00\P01\P02). When the IO port outputs low level, the LED is lit, and vice versa.
The low level is when the button is pressed, and the light is on when the scan button is low level.
Timer/counter working principle
Timer timing time calculation formula (16bit):

Insert image description here

/*程序代码及注释:
项目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();
	}
} 


Experiment 4 STC8h1k28 digital tube stopwatch program design

Experimental content:
Project:

Use digital tubes, buttons and internal timing to implement the second timing function. The maximum timing is 9999 seconds. If the timeout exceeds 9999 seconds, the count will be cleared. The external button KEY1 controls the start and stop of the stopwatch, and the button KEY2 clears the stopwatch timing.
Principle diagram: Insert image description here
Insert image description here
Experimental principle:
Nigital tube display and dynamic scanning
When the button is pressed, it is low level, and when the scanning button is low level, the light is on.
(Common anode) The cathode of the digital tube is connected to the IO port of the microcontroller. When the IO port outputs low level, the corresponding segment or bit selection is lit, otherwise it is turned off.

//程序代码及注释:
#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);//循环体,啥也不执行在这耗时,保证个定时器功能瞬时间流逝时执行
}
 


Experiment 5 STC8h1k28 microcontroller and PC serial communication

Experiment content:
Project:

The PC sends character instructions to the microcontroller through the serial port debugging assistant. After receiving the instruction, the microcontroller will light up or turn off the corresponding LED according to the instruction, and send the instruction back to the PC, and display it in the receiving buffer of the serial port debugging assistant. The command comparison table is as follows:
R—red light on; G—green light on; B—blue light on; A—all lights on; O—all lights off.
Experimental principle:
1. A level conversion module is used to connect the microcontroller and PC to realize the physical connection and level conversion between the serial port of the microcontroller and the USB interface of the PC. Asynchronous serial communication is used between the microcontroller and the PC. The baud rate is 9600, the information format is 8 data bits, 1 stop bit, and no parity bit. The PC can use the "serial port debugging assistant" embedded in the STC-ISP software for debugging.
2. Baud rate calculation formula
Insert image description here

3. Serial port assistant embedded in STC-ISP online programming tool. Insert image description here
Schematic:
Insert image description here

//程序代码及注释:
#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);//耗时
}
 


Experiment 6 STC8h1k28 ADC-based analog key recognition and control

Experiment content:
Project:

Send the analog button key values ​​to the serial port debugging assistant of the PC through the serial port, and control the light-emitting diodes on the evaluation version to turn on and off through the four analog buttons. The control method is as follows: When button 1 is pressed, the blue light will be on, when button 2 is pressed, the red light will be on, when button 3 is pressed, the green light will be on, when button
4 is pressed, all three colors of lights will be on, and when no button is pressed, all lights will go out.
Principle diagram:
Insert image description here
Insert image description here
Experimental principle:
 Press different analog buttons to simulate the channel port to get different analog values. The ADC converts the corresponding values ​​​​to the CPU, and then selects the control light to turn on and off through the switch-case cycle;  (Common anode)
LED negative pole is connected to the IO port of the microcontroller (P00\P01\P02), when the IO port outputs low level, the LED is lit, otherwise
it is turned off;
 PC serial port debugging assistant.

//程序代码及注释:

#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值控制亮灯函数 
	}
}
 
 

Guess you like

Origin blog.csdn.net/m0_53126906/article/details/125711105