STC15W4K32S4单片机ADC应用实现

感谢北京化工大学何宾老师的课程指导,今天我们分享一个利用STC15W4K32S4单片机实现的ADC应用,我们通过ADC转换实现在LCD1602上显示学号,并能够通过外部中断0和外部中断1分别实现学号左移和右移的功能。

以下是项目代码:

1、lcd1602.h

// 条件编译指令,如果未定义_1602_则定义_1602
#ifndef _1602_
#define _1602_

// 引入头文件
#include "reg51.h"
#include "intrins.h"

// 定义LCD引脚及寄存器地址
sbit LCD1602_RS = P2^5; // 定义LCD1602_RS为P2.5引脚,RS=0表示传输的是控制指令,RS=1表示传输的是数据
sbit LCD1602_RW = P2^6; // 定义LCD1602_RW为P2.6引脚,R/W=0表示读操作,R/W=1表示写操作
sbit LCD1602_E  = P2^7; // 定义LCD1602_E 为P2.7引脚,E=1,单片机将数据放入数据线,一段时间后拉低,数据继续维持一段时间,即写入LCD中
sfr  LCD1602_DB = 0x80; // 定义LCD1602_DB为P0端口
sfr  P0M1       = 0x93; // 定义P0端口P0M1寄存器地址0x93
sfr  P0M0       = 0x94; // 定义P0端口P0M0寄存器地址0x94
sfr  P2M1       = 0x95; // 定义P2端口P2M1寄存器地址0x95
sfr  P2M0       = 0x96; // 定义P2端口P2M0寄存器地址0x96

// 申明函数
void lcdwait();															// 等待LCD空闲函数
void lcdwritecmd(unsigned char cmd);									// 写LCD命令函数
void lcdwritedata(unsigned char dat);									// 写LCD数据函数
void lcdinit();															// 初始化LCD函数
void lcdsetcursor(unsigned char x, unsigned char y);					// 设定LCD光标位置函数
void lcdshowstr(unsigned char x, unsigned char y, unsigned char *str);	// 打印字符串函数

// 条件预编译指令结束
#endif

2、led1602.c

// 引入头文件
#include "led1602.h"

// 实现函数
/**
 * 函数名:lcdwait()
 * 参数  :无
 * 功能  :等待LCD空闲
 */
void lcdwait() {
	LCD1602_DB = 0xFF;			// 读取前,置P0端口为FF,引脚相当于悬空
	_nop_();					// 空操作指令,延迟
	_nop_();
	_nop_();
	_nop_();
	LCD1602_RS = 0;				// 将RS信号拉低
	LCD1602_RW = 1;				// 将RW信号拉高
	LCD1602_E  = 1;				// 将E 信号拉高
	while(LCD1602_DB & 0x80);	// 等待标志BF为低,即LCD空闲
    LCD1602_E  = 0;				// 将E 信号拉低
}

/**
 * 函数名:lcdwritecmd()
 * 参数  :cmd			控制指令码
 * 功能  :写LCD命令
 */
void lcdwritecmd(unsigned char cmd) {
	lcdwait();			// 等待LCD空闲
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	LCD1602_RS = 0;
	LCD1602_RW = 0;
	LCD1602_DB = cmd;	// 将控制指令码放到P0端口
	LCD1602_E  = 1;
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	LCD1602_E  = 0;
}

/**
 * 函数名:lcdwritecmd()
 * 参数  :dat			数据码
 * 功能  :写LCD数据
 */
void lcdwritedata(unsigned char dat) {
	lcdwait();			// 等待LCD空闲
    _nop_();
	_nop_();
	_nop_();
	_nop_();
	LCD1602_RS = 1;
	LCD1602_RW = 0;
	LCD1602_DB = dat;	// 将数据码放到P0端口
	LCD1602_E  = 1;
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	LCD1602_E  = 0;
}

/**
 * 函数名:lcdinit()
 * 参数  :无
 * 功能  :初始化LCD
 */
void lcdinit() {
	lcdwritecmd(0x38);	// 发指令0x38,2行模式,5x8点阵,8位宽度
	lcdwritecmd(0x0c);	// 发指令0x0c,打开显示,关闭光标
	lcdwritecmd(0x06);	// 发指令0x06,文字不移动,地址自动加1
	lcdwritecmd(0x01);	// 发指令0x01,清屏
}

/**
 * 函数名:lcdsetcursor()
 * 参数  :x			在LCD上的列数
 *         y			在LCD上的行数
 * 功能  :设定LCD光标位置
 */
void lcdsetcursor(unsigned char x, unsigned char y) {
	unsigned char address;			// 存储器地址
	if(y==0)						// 在第一行
		address = 0x00 + x;
	else							// 在第二行
		address = 0x40 + x;
	lcdwritecmd(address | 0x80);	// 写存储器地址指令
}

/**
 * 函数名:lcdshowstr()
 * 参数  :x			在LCD上的列数
 *         y			在LCD上的行数
 *         str			需要打印的字符串
 * 功能  :打印字符串
 */
void lcdshowstr(unsigned char x, unsigned char y, unsigned char *str) {
	lcdsetcursor(x, y);			// 设置光标位置
	while((*str) != '\0') {		// 字符串未到结尾
		 lcdwritedata(*str);	// 传送字符数据
		 str++;					// 字符串地址自增
	}
}									

3、main.c

// 引入头文件
#include "reg51.h"
#include "stdio.h"
#include "led1602.h"

#define ADC_POWER     0x80		// 定义ADC_POWER  的值为0x80
#define ADC_FLAG      0x10		// 定义ADC_FLAG   的值为0x10
#define ADC_START     0x08		// 定义ADC_START  的值为0x08
#define ADC_SPEEDLL   0x00		// 定义ADC_SPEEDLL的值为0x00
#define ADC_SPEEDL    0x20		// 定义ADC_SPEEDL 的值为0x20
#define ADC_SPEEDH    0x40		// 定义ADC_SPEEDH 的值为0x40
#define ADC_SPEEDHH   0x60		// 定义ADC_SPEEDHH的值为0x60

sfr AUXR      = 0x8E;			// 申明AXUR寄存器的地址为0x8E
sfr ADC_CONTR = 0xBC;			// 申明ADC_CONTR控制寄存器的地址为0xBC
sfr ADC_RES   = 0xBD;			// 申明ADC_RES结果寄存器的地址为0xBD
sfr ADC_RESL  = 0xBE;			// 申明ADC_RESL结果寄存器的地址为0xBE
sfr P1ASF     = 0x9D;			// 申明P1ASF模拟功能控制寄存器的地址为0x9D

// 在外部数据区定义变量,用于存储学号
xdata long  num1 _at_ 0x100;	// 定义长整形变量num1
xdata float num2 _at_ 0x120;	// 定义浮点数变量num2

unsigned char ch = 4;
bit flag = 1;					// ADC转换完成标识
unsigned char tstr[50];			// 数据存储缓冲器

/**
 * 函数名:delay
 * 参数  :n			延迟时间长度,单位毫秒
 * 功能  :延时指定的毫秒时间
 */
void delay(unsigned int n) { 
	unsigned int i, j; 
	for(i = n; i > 0; i--) {
		for(j = 114; j > 0; j--);
	}		
}

/**
 * 函数名:adc_int
 * 参数  :无
 * 功能  :ADC中断响应函数
 */
void adc_int() interrupt 5 {
	unsigned char i = 0;
	ADC_CONTR &= !ADC_FLAG;									// 将ADC_FLAG标志清零
	num1 = 2016014446;
	num2 = 2016014446;
	sprintf(tstr + 10, "%lld", num1);						// 将数据传送至缓冲区
	flag = 1;												// ADC转换完成
	ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;	// 启动ADC
}

/**
 * 函数名:move_left
 * 参数  :无
 * 功能  :外部中断0中断响应函数,实现学号在LCD上左移
 */
void move_left() interrupt 0 {
	unsigned char i;
	for(i = 0; i < 11; i++){
		lcdwritecmd(0x01);								// 清屏
		lcdwait();										// 等待LCD空闲
		lcdshowstr(0, 0, tstr+10+i);					// 右移数组地址,写字符串
		lcdwait();
		delay(3000);									// 延时等待
	}
}

/**
 * 函数名:move_right
 * 参数  :无
 * 功能  :外部中断1中断响应函数,实现学号在LCD上右移
 */
void move_right() interrupt 2 {
	unsigned char i;
	for(i = 6; i < 17; i++){
		lcdwritecmd(0x01);								// 清屏
		lcdwait();										// 等待LCD空闲
		lcdshowstr(i, 0, tstr+10);						// 右移光标位置,写字符串
		lcdwait();
		delay(3000);									// 延时等待
	}
}

/**
 * 函数名:main
 * 参数  :无
 * 功能  :主函数,在LCD上打印学号,响应中断
 */
void main() {
	unsigned int i, k;
	P0M0 = 0;		// 通过P0M0和P0M1寄存器将P0口定义为准双向(双向IO),弱上拉(上拉电阻很大,提供的驱动电流很小,叫弱上拉)
	P0M1 = 0;
	P2M0 = 0;		// 通过P2M0和P2M1寄存器将P2口定义为准双向,弱上拉
	P2M1 = 0;
	P1ASF = 0xFF;	// 将P1端口用于ADC输入
	ADC_RES = 0;	// 将ADC_RES寄存器清零
	ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;	// 配置ADC_CONTR寄存器
	for(i = 0; i < 10000; i++);
	IE = 0xA0;		// 允许ADC中断
	lcdwait();		// 等待LCD空闲
	lcdinit();		// 初始化LCD
	IT0 = 1;		// 开启外部中断0和外部中断1
	EX0 = 1;
	IT1 = 1;
	EX1 = 1;
	EA  = 1;
	while(1) { 
		if(flag == 1) {
			flag = 0;
			for(k = 0; k < 16; k++) {// 循环打印学号
				lcdwritecmd(0x01);
				lcdwait();
				lcdshowstr(k, 0, tstr+10);
				if(k > 6)
					lcdshowstr(0, 0, tstr+26-k);
				lcdwait();
				delay(500);
			}
		}
	}
}

有关讲解的视频欢迎关注我们的公众号:落饼枫林,查看历史推送:STC15W4K32S4单片机ADC应用实现。

想要学习更多单片机的知识也欢迎参加何老师在爱课程网站上的单片机原理及应用的课程:https://www.icourse163.org/learn/BUCT-1205804839#/learn/announce

<think>嗯,用户想了解STC15W4K32S4单片机的数据手册、引脚图和示例代码。首先,我需要查看提供的引用内容,看看是否有相关信息。引用[1]提到了中文手册的下载,里面有硬件结构、寄存器配置和编程示例,这应该涵盖数据手册的内容。然后引用[2]和[4]提到了引脚图,特别是引用[4]提到了P3接口和其他引脚的内部结构图,可能需要引导用户到这些资源。示例代码方面,引用[3]有一个关于PWM频率和占空比调节的C语言程序,还有掉电存储功能,这可以作为示例代码的参考。 接下来,我需要将这些信息组织成结构清晰的回答,分点说明数据手册、引脚图和示例代码的获取方式和使用方法。同时,按照用户的要求,生成相关问题,比如手册内容、引脚功能、PWM应用等。还要注意正确使用LaTeX格式,比如数学表达式用$包裹,独立公式用$$,不过当前问题可能不太涉及数学公式,但如果有参数计算可能需要用到。另外,确保引用标识正确添加在每个引用的末尾,如[^1]、[^2]等。 需要确认用户可能的需求,比如开发环境、具体应用场景,所以在回答中提到了KEIL环境和PWM示例。同时,提醒注意事项,比如结合具体需求调整代码,安装KEIL等。可能用户是刚开始学习这款单片机,所以说明要详细但简洁,引导他们到正确的资源位置。 最后,生成的相关问题要围绕用户可能进一步想知道的内容,比如手册的其他内容、引脚复用功能、PWM应用案例和掉电存储实现方法。这些问题可以帮助用户深入学习和开发。</think>### STC15W4K32S4单片机信息汇总 #### 1. **数据手册** STC15W4K32S4单片机的中文手册详细介绍了其硬件架构、功能模块(如定时器、PWM、ADC等)及寄存器配置方法[^1]。手册还包含KEIL环境下的编程示例,适合开发参考。 - **下载方式**:通过仓库资源获取`STC15W4K32S4中文手册.pdf`,需配合KEIL开发环境使用。 - **关键参数**: - 程序存储器容量:16K~63.5KB Flash,支持10万次擦写 - 工作频率:最高35MHz #### 2. **引脚图与功能** 该单片机的引脚支持多种复用功能(如GPIO、PWM输出、串口通信等),引脚图可参考以下资源: - **引用[4]**:展示了P3接口的复用功能及内部结构图[^4] - **引用[2]**:提供管脚图及引脚分配说明 #### 3. **示例代码** **PWM频率占空比调节程序**(引用[3]): ```c // 示例代码片段:通过旋转编码器调整PWM参数并保存设置 #include "stc15.h" #include "eeprom.h" void PWM_Init() { P_SW2 |= 0x80; // 使能访问XSFR寄存器 PWMCFG = 0x00; // 配置PWM模式 // ... 其他初始化代码 } void main() { PWM_Init(); while(1) { // 读取编码器输入并更新PWM // 保存参数至EEPROM } } ``` - **功能说明**:支持PWM频率/占空比实时调节,且参数掉电存储[^3] #### 4. **开发注意事项** - 需安装STC-ISP软件烧录程序[^3] - 复用引脚需根据数据手册配置寄存器[^4] --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值