STC8H8K系列汇编和C51实战——数码管显示ADC、按键串口回复按键号与ADC数值

数码管显示ADC、串口显示ADC按键与数值


一、题目

实现了通过与通道ADC0相连的16个ADC按键引起的模拟电压信号变化的测量,用实验箱上的数码管高2位显示键码,低4位显示AD值。使用串口1在主机串口助手上显示键值和转换结果数值, 显示格式为: 键值:对应ADC结果。继续按键回车换行,以同样格式显示下一个键值及其ADC结果。


二、代码

main函数

//高2位显示键码,低4位显示AD值
#include<stc8h.h>
#include<intrins.h>
#define uchar unsigned char
#define uint  unsigned int

bit busy;
u8 key=0;
uchar cnt1ms=0;
uint ad_volume=0;
#define	ADC_OFFSET	64
uchar KeyCode=0;
void	CalculateAdcKey(uint adc);
uint	Get_ADC12bitResult(uchar channel);	//channel = 0~7

#define font_PORT  P6             //定义字形码输出端口
#define position_PORT  P7         //定义位控制码输出端口
uchar code  LED_SEG[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0x40,0x79,0x24,0x30,0x19,0x12d,0x02,0x78,0x00,0x10,0xbf };  
  //定义"0、1、2、3、4、5、6、7、8、9","A、B、C、D、E、F"以及"灭"的字形码
  //定义"0、1、2、3、4、5、6、7、8、9"(含小数点)的字符以及“-”的字形码
uchar code  Scan_bit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf, 0xbf, 0x7f};   //定义扫描位控制码
uchar data  Dis_buf[]={16,16,16,16,16,16,16,0};   //定义显示缓冲区,最低位显示"0",其它为"灭"

void gpio()		//gpio初始化为准双向口,刚开始除了P30,P31其他均为高阻态
{
    P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
}


/*----------------------------
发送字节
----------------------------*/
void SendData(uchar dat)
{
    while (busy);               
    busy = 1;
    SBUF = dat;                 //要发送的数据存入SBUF
}

/*----------------------------
发送字符串函数
----------------------------*/
void SendString(uchar *s)
{
    while (*s !='\0')                  //字符串被读取完才停止
    {
        SendData(*s++);         //每发送完一个字节s++
    }
} 


void Timer0Init(void)		//1毫秒@24.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x40;		//设置定时初值
	TH0 = 0xA2;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}

/*――――――――――延时函数――――――――――――*/
void Delay1ms()		//@24.000MHz
{
	unsigned char i, j;

	_nop_();
	i = 32;
	j = 40;
	do
	{
		while (--j);
	} while (--i);
}

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

	i = 16;
	j = 147;
	do
	{
		while (--j);
	} while (--i);
}



/*――――――――――显示函数――――――――――――*/
void LED_display(void)
{
	uchar i;
	for(i=0;i<8;i++)
	{
		position_PORT =0xff; font_PORT =LED_SEG[Dis_buf[i]]; position_PORT = Scan_bit[7-i]; 			Delay500us();
	}	
}

/*――――――――――串口初始化――――――――――――*/
void InitUART(void)
{
    SCON = 0x50;                //8位数据	
	  P_SW1= P_SW1 & 0x3F; 
    AUXR |= 0x40;                //定时器1T模式
	  AUXR &= 0xFE;	
    TMOD &= 0x0F;
    TMOD |= 0x20;                //8位自动重装载模式
    TL1 = 0xDC;   				//
    TH1 = 0xDC;
    TR1 = 1;                    //开启定时器1
    ES = 1;                     //开启串口中断
    EA = 1;

}
/**********************************************/
void main(void)
{
	uint	j;
	gpio();
    ADCCFG=ADCCFG|0x20;	//RESFMT位置1,存储结果右对齐
	ADC_CONTR = 0x80;	//打开AD转换模块电源
	P1M1=P1M1|0x01;	//P1口设为高阻态
	Timer0Init();
	InitUART();
	ET0 = 1;	//Timer0 interrupt enable
	TR0 = 1;	//Tiner0 run
	EA = 1;		//打开总中断
	while(1)
	{
		Dis_buf[4] = ad_volume / 1000%10;	//显示ad值
		Dis_buf[5] = ad_volume/100%10;	//显示ad值
		Dis_buf[6] = ad_volume / 10%10;	//显示ad值
		Dis_buf[7] = ad_volume % 10;	   //显示ad值
		Dis_buf[0] = KeyCode / 10;	//显示键码
		Dis_buf[1] = KeyCode % 10;	//显示键码 
		LED_display();	  
		
		if(cnt1ms >= 10)	//10ms读一次ADC
		{
			cnt1ms = 0;
			j = Get_ADC12bitResult(0);	//0通道,查询方式做一次ADC, 返回值就是结果, == 4096 为错误
		    if(((256-ADC_OFFSET)<j)&&(j < 4096))
			{
			  	LED_display();	//去抖
				LED_display();
				j = Get_ADC12bitResult(0);	
				if(((256-ADC_OFFSET)<j)&&(j < 4096))
				{ 
					ad_volume=j;
			 		CalculateAdcKey(j);	//计算按键
					SendData(KeyCode/10+0x30);
					SendData(KeyCode%10+0x30);
					SendString(": ");
					
					SendData(ad_volume / 1000%10+0x30);
					SendData(ad_volume/100%10+0x30);
					SendData(ad_volume / 10%10+0x30);
					SendData(ad_volume % 10+0x30);
					SendString("\r\n");
					
					Dis_buf[4] = ad_volume / 1000%10;	//显示ad值
					Dis_buf[5] = ad_volume/100%10;	//显示ad值
					Dis_buf[6] = ad_volume / 10%10;	//显示ad值
					Dis_buf[7] = ad_volume % 10;	   //显示ad值
					Dis_buf[0] = KeyCode / 10;	//显示键码
					Dis_buf[1] = KeyCode % 10;	//显示键码 
					LED_display();
L1:					j = Get_ADC12bitResult(0);
					while(((256-ADC_OFFSET)<j)&&(j < 4096))	   //键释放
					{
						  LED_display();
						  goto L1;
					}
				}	
			}							  
		}		

	 }
}


/****************测量AD值*************************/
uint	Get_ADC12bitResult(uchar channel)	//channel = 0~15
{
	ADC_RES = 0;	//将转换结果寄存器清0
	ADC_RESL = 0;

	ADC_CONTR = (ADC_CONTR & 0xe0) | 0x40 | channel; 	//先上电,再开始,再选择通道
	_nop_();  	_nop_(); 	_nop_();	_nop_();//第一次开始的时候需要等待电路稳定

	while((ADC_CONTR & 0x20) == 0)	;	//等待ADC完成
	ADC_CONTR &= ~0x20;		//清除ADC结束标志
	return	(((uint)ADC_RES << 8) | ADC_RESL );
}

/***************** ADC键盘计算键码 ********************************/

void	CalculateAdcKey(uint adc)
{
	uchar	i;
	uint	j=256;
	for(i=1; i<=16; i++)
	{
		if((adc >= (j - ADC_OFFSET)) && (adc <= (j + ADC_OFFSET)))	break;	//判断是否在偏差范围内
		j += 256;
	}
	if(i < 17)	KeyCode  = i;	//保存键码
						
}

/********************** Timer0 1ms中断函数 ************************/
void timer0 (void) interrupt 1
{
	cnt1ms++;	
}

/*----------------------------
UART 中断
-----------------------------*/
void Uart() interrupt 4 using 1
{
	LED_display();	  
    if (RI)
    {
        RI = 0;                 //接收到字符后,RI清0
		
    }
    if (TI)
    {
        TI = 0;                 //发送完字符后TI清0
        busy = 0;               //发送完一个字符后busy清0
	}
}

LED_display函数

// 以下为LED_display.c
#include <stc8h.h>
#include <intrins.h>

#define font_PORT  P6             //定义字形码输出端口
#define position_PORT  P7         //定义位控制码输出端口
uchar code  LED_SEG[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0x40,0x79,0x24,0x30,0x19,0x12d,0x02,0x78,0x00,0x10,0xbf };  
  //定义"0、1、2、3、4、5、6、7、8、9","A、B、C、D、E、F"以及"灭"的字形码
  //定义"0、1、2、3、4、5、6、7、8、9"(含小数点)的字符以及“-”的字形码
uchar code  Scan_bit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf, 0xbf, 0x7f};   //定义扫描位控制码
uchar data  Dis_buf[]={16,16,16,16,16,16,16,0};   //定义显示缓冲区,最低位显示"0",其它为"灭"

/*――――――――――延时函数――――――――――――*/
void Delay1ms()		//@24.000MHz
{
	unsigned char i, j;

	_nop_();
	i = 32;
	j = 40;
	do
	{
		while (--j);
	} while (--i);
}


/*――――――――――显示函数――――――――――――*/
void LED_display(void)
{
	uchar i;
	for(i=0;i<8;i++)
	{
		position_PORT =0xff; font_PORT =LED_SEG[Dis_buf[i]]; position_PORT = Scan_bit[7-i]; 			Delay1ms ();
	}	
}



LED_display.h头文件

#ifndef __LED_DISPLAY_H__
#define __LED_DISPLAY_H__
 
void Delay1ms();
 void LED_display(void);
 
 uchar code  LED_SEG[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0x40,0x79,0x24,0x30,0x19,0x12d,0x02,0x78,0x00,0x10,0xbf };  
  //定义"0、1、2、3、4、5、6、7、8、9","A、B、C、D、E、F"以及"灭"的字形码
  //定义"0、1、2、3、4、5、6、7、8、9"(含小数点)的字符以及“-”的字形码
uchar code  Scan_bit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf, 0xbf, 0x7f};   //定义扫描位控制码
uchar data  Dis_buf[]={16,16,16,16,16,16,16,0};   //定义显示缓冲区,最低位显示"0",其它为"灭"
#end if

非常感谢各位观看!!!

系列文章——STC8H8K系列汇编51实战

基于ESP8266与STC单片机的天气时钟(包括DS18B20、TFT、串口、外部中断、ESP8266、STC、API等)

STC8H8K系列汇编和C51实战——实现跑马灯(51版)

STC8H8K系列汇编和C51实战——实现跑马灯(汇编版)

STC8H8K系列汇编和C51实战——实现键控不同方式数码管动态显示(C51版与汇编版)

STC8H8K系列汇编和C51实战——开关控制定时器秒表(C51版)

STC8H8K系列汇编和C51实战——开关控制定时器秒表(汇编版)

STC8H8K系列汇编和C51实战——双中断控制定时器流水灯

STC8H8K系列汇编和C51实战——双中断加减计数器

STC8H8K系列汇编和C51实战——简易频率计

STC8H8K系列汇编和C51实战——秒倒计时器(汇编版)

STC8H8K系列汇编和C51实战——秒倒计时器(51版)

STC8H8K系列汇编和C51实战——秒倒计时器(可自行设定初值)(51版)

STC8H8K系列汇编和C51实战——按键允许按键计数(51版)

STC8H8K系列汇编和C51实战——按键允许按键计数(汇编版)

STC8H8K系列汇编和C51实战——按键允许按键计数(定时器去抖动51版)

STC8H8K系列汇编和C51实战——按键允许按键计数(利用下降沿中断控制)

STC8H8K系列汇编和C51实战——计算机串口控制单片机LED

STC8H8K系列汇编和C51实战——串口发送菜单界面选择不同功能

STC8H8K系列汇编和C51实战——数码管显示ADC、串口显示ADC按键与数值

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不知何人

万分感谢诸位观看

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

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

打赏作者

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

抵扣说明:

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

余额充值