2015-11-26 21:37:25 chengdong1314 阅读数 1141
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3395 人正在学习 去看看 朱有鹏

这篇文章讲51芯片内部各个模块的汇编程序,这里不做实验,只贴代码:

外部中断模块-汇编:


中断地址定义:

  ;-----------------------------------------------
  ORG 0000H  ;伪指令 告诉编译器从0000H开始
  LJMP MAIN  ;64KB无条件跳转 跳转到main处执行
  ORG 0003H     ;中断入口
  LJMP exter0  ;中断函数名
  ORG 0013H     ;中断入口
  LJMP exter1  ;中断函数名
  ORG 0100H  ;虽然这里是伪指令 但是确实有标明地址的作用
  ;-----------------------------------------------


主函数  main:

MAIN:
  MOV SP,#3FH   ;设置栈低为5FH
  LCALL DELAY40ms          ;延时40.301ms 64KB长调用子函数
  MOV num,#00H
  MOV wei,#07H
  SETB EX0        ;开启外部中断 0,即P32引脚
  SETB IT0      ;将外部中断0设为边沿触发方式
  CLR PX0        ;优先级为0    
  SETB EX1    
  SETB IT1   
  SETB PX1  ;1的中断优先级比0的高   外部中短1的优先级比0的高
  SETB EA        ;首先开启总中断
  ;********************死循环**********************

while1:
  LCALL led_Static_display
  INC num
  MOV A,num
  CJNE A,#011H,rigthnum
  MOV num,#00H
  rigthnum:
  LCALL DELAY500ms
  LCALL DELAY500ms
  LJMP while1
  ;================================================
  ;外部中断0函数
  ;================================================




中断函数:

exter0:    
  ;CLR EA
  PUSH 31H
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  PUSH 05H    
  PUSH 06H
  PUSH 07H
  ;SETB p3.2   ;延时消抖 这是一个方法,否则出中断的时候会出现错误
  ;LCALL DELAY40ms
  ;JB p3.2,OVER
  MOV numtemp,#03H
  while1exter0:
  MOV num,numtemp
  LCALL led_Static_display
  LCALL DELAY500ms
  MOV num,#10H  ;闪烁
  LCALL led_Static_display
  LCALL DELAY500ms
  DEC numtemp     
  MOV A,numtemp    
  CJNE A,#0FFH,while1exter0
  OVER:
  POP 07H    
  POP 06H
  POP 05H    
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  POP 31H
  CLR IE0   ;进中断的时候关中断,出中断的时候开中断,并清除中断标志位 这是方法二
  SETB EA
  RETI        ;中断结束返回
  ;================================================
  ;外部中断1函数
  ;================================================
exter1:    
  ;CLR EA
  PUSH 32H
  PUSH 31H
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  PUSH 05H    
  PUSH 06H
  PUSH 07H
  SETB p3.3   ;延时消抖 这是一个方法,否则出中断的时候会出现错误
  LCALL DELAY40ms
  JB p3.3,OVERexter1
  MOV numtemp,#04H
  while1exter1:
  MOV num,numtemp
  LCALL led_Static_display
  LCALL DELAY500ms
  MOV num,#10H  ;闪烁
  LCALL led_Static_display
  LCALL DELAY500ms
  INC numtemp     
  MOV A,numtemp    
  CJNE A,#08H,while1exter1
  OVERexter1:
  POP 07H    
  POP 06H
  POP 05H    
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  POP 31H
  POP 32H
  CLR IE1   ;进中断的时候关中断,出中断的时候开中断,并清除中断标志位 这是方法二
  ;SETB EA
  RETI        ;中断结束返回
  ;================================================
  ;数码管静态显示函数
  ;================================================


整个程序源代码:

  ;-----------------------数码管脚功能定义---------------------------   
  LED_wei EQU P2
  LED138_0 EQU P2.0
  LED138_1 EQU P2.1
  LED138_2 EQU P2.2
  LED_duan EQU P0
  ;-------------------- 数码要显示的位、数据---------------------------
  wei EQU 30H    ;数码管位选
  num EQU 31H    ;数码管段选
  numtemp EQU 32H    ;数码管段选暂存
  ;-----------------------------------------------
  ORG 0000H  ;伪指令 告诉编译器从0000H开始
  LJMP MAIN  ;64KB无条件跳转 跳转到main处执行
  ORG 0003H     ;中断入口
  LJMP exter0  ;中断函数名
  ORG 0013H     ;中断入口
  LJMP exter1  ;中断函数名
  ORG 0100H  ;虽然这里是伪指令 但是确实有标明地址的作用
  ;-----------------------------------------------
MAIN:
  MOV SP,#3FH   ;设置栈低为5FH
  LCALL DELAY40ms          ;延时40.301ms 64KB长调用子函数
  MOV num,#00H
  MOV wei,#07H
  SETB EX0        ;开启外部中断 0,即P32引脚
  SETB IT0      ;将外部中断0设为边沿触发方式
  CLR PX0        ;优先级为0    
  SETB EX1    
  SETB IT1   
  SETB PX1  ;1的中断优先级比0的高   外部中短1的优先级比0的高
  SETB EA        ;首先开启总中断
  ;********************死循环**********************
while1:
  LCALL led_Static_display
  INC num
  MOV A,num
  CJNE A,#011H,rigthnum
  MOV num,#00H
  rigthnum:
  LCALL DELAY500ms
  LCALL DELAY500ms
  LJMP while1
  ;================================================
  ;外部中断0函数
  ;================================================
exter0:    
  ;CLR EA
  PUSH 31H
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  PUSH 05H    
  PUSH 06H
  PUSH 07H
  ;SETB p3.2   ;延时消抖 这是一个方法,否则出中断的时候会出现错误
  ;LCALL DELAY40ms
  ;JB p3.2,OVER
  MOV numtemp,#03H
  while1exter0:
  MOV num,numtemp
  LCALL led_Static_display
  LCALL DELAY500ms
  MOV num,#10H  ;闪烁
  LCALL led_Static_display
  LCALL DELAY500ms
  DEC numtemp     
  MOV A,numtemp    
  CJNE A,#0FFH,while1exter0
  OVER:
  POP 07H    
  POP 06H
  POP 05H    
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  POP 31H
  CLR IE0   ;进中断的时候关中断,出中断的时候开中断,并清除中断标志位 这是方法二
  SETB EA
  RETI        ;中断结束返回
  ;================================================
  ;外部中断1函数
  ;================================================
exter1:    
  ;CLR EA
  PUSH 32H
  PUSH 31H
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  PUSH 05H    
  PUSH 06H
  PUSH 07H
  SETB p3.3   ;延时消抖 这是一个方法,否则出中断的时候会出现错误
  LCALL DELAY40ms
  JB p3.3,OVERexter1
  MOV numtemp,#04H
  while1exter1:
  MOV num,numtemp
  LCALL led_Static_display
  LCALL DELAY500ms
  MOV num,#10H  ;闪烁
  LCALL led_Static_display
  LCALL DELAY500ms
  INC numtemp     
  MOV A,numtemp    
  CJNE A,#08H,while1exter1
  OVERexter1:
  POP 07H    
  POP 06H
  POP 05H    
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  POP 31H
  POP 32H
  CLR IE1   ;进中断的时候关中断,出中断的时候开中断,并清除中断标志位 这是方法二
  ;SETB EA
  RETI        ;中断结束返回
  ;================================================
  ;数码管静态显示函数
  ;================================================
led_Static_display:
  ANL wei, #07H
  ANL LED_wei,#0F8H
  MOV A,wei
  ORL LED_wei,A
  MOV A,num  
  MOV DPTR,#numtab
  MOVC A,@A+DPTR  ;查表取数据
  MOV LED_duan,A
  RET
  ;================================================
  ;各种参数的延时子函数
  ;================================================
DELAY100us:     ;100us  
  MOV R6,#06H
  DEL11: MOV R7,#08H
  DEL12: DJNZ R7,DEL12
  DJNZ R6,DEL11
  RET

DELAY500us:    ;500us
  MOV R6,#0CH   ;288
  DEL21: MOV R7,#18H
  DEL22: DJNZ R7,DEL22
  DJNZ R6,DEL21
  RET
 
DELAY1ms:    ;1ms
  MOV R6,#18H   
  DEL61: MOV R7,#18H
  DEL62: DJNZ R7,DEL62
  DJNZ R6,DEL61
  RET

DELAY40ms:    ;延时40ms  500得1ms
  MOV R6,#100
  DEL41: MOV R7,#200
  DEL42: DJNZ R7,DEL42
  DJNZ R6,DEL41
  RET

DELAY256ms:        ;延时256ms
  MOV R5,#05H
  DEL51: MOV R6,#100
  DEL52: MOV R7,#0FFH
  DEL53: DJNZ R7,DEL53
  DJNZ R6,DEL52
  DJNZ R5,DEL51
  RET
 
DELAY500ms:        ;延时256ms
  MOV R5,#0AH
  DEL81: MOV R6,#100
  DEL82: MOV R7,#0FFH
  DEL83: DJNZ R7,DEL83
  DJNZ R6,DEL82
  DJNZ R5,DEL81
  RET
 
DELAY1s:    ;1秒
  MOV R5,#16H
  DEL31: MOV R6,#100
  DEL32: MOV R7,#0FFH
  DEL33: DJNZ R7,DEL33
  DJNZ R6,DEL32
  DJNZ R5,DEL31
  RET
 
DELAY10s:    ;10秒
  MOV R5,#0DCH
  DEL71: MOV R6,#100
  DEL72: MOV R7,#0FFH
  DEL73: DJNZ R7,DEL73
  DJNZ R6,DEL72
  DJNZ R5,DEL71
  RET
numtab: DB  03FH,006H,05BH,04FH,066H,06DH,07DH,007H,07FH,06FH,077H,07CH,039H,05EH,079H,071H,000H
end


keil工程整体源码:

51汇编之外部中断带优先级-汇编.zip

http://download.csdn.net/detail/chengdong1314/9303641

2015-01-24 16:46:12 qq_16255321 阅读数 7376
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3395 人正在学习 去看看 朱有鹏

很多单片机都有低功耗模式, STM32 也不例外。在系统或电源复位以后,微控制器处于运行状态。运行状态下的 HCLK 为 CPU 提供时钟,内核执行程序代码。当 CPU 不需继续运行时,可以利用多个低功耗模式来节省功耗,例如等待某个外部事件时。用户需要根据最低电源消耗,最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。


STM32 的低功耗模式有 3 种:
1)睡眠模式( CM3 内核停止,外设仍然运行)
2)停止模式(所有时钟都停止)
3)待机模式( 1.8V 内核电源关闭)


   
在这三种低功耗模式中,最低功耗的是待机模式,在此模式下,最低只需要 2uA 左右的电流。停机模式是次低功耗的,其典型的电流消耗在 20uA 左右。最后就是睡眠模式了。用户可以根据自己的需求来决定使用哪种低功耗模式。
本节实验是待机模式的实验,根据上表可以看到有4种方式进入待机模式,我们选择第一种,即通过WK_UP的外部中断来触发进入待机模式的方式
配置步骤:
1)使能电源时钟。
2) 设置 WK_UP 引脚作为唤醒源。
3)设置 SLEEPDEEP 位,设置 PDDS 位,执行 WFI 指令,进入待机模式。
4)最后编写 WK_UP 中断函数。


wkup.c 
#include "wkup.h"
//待命模式
void Sys_Standby(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //使能 PWR外设时钟
	PWR_WakeUpPinCmd(ENABLE); //使能唤醒管脚功能
	PWR_EnterSTANDBYMode();  //进入待命( STANDBY)模式
}
//系统进入待机模式
void Sys_Enter_Standby(void)
{
	RCC_APB2PeriphResetCmd(0X01FC,DISABLE); //复位所有 IO 口
	Sys_Standby();
}

//检测 WKUP 脚的信号
//返回值 1:连续按下 3s 以上
// 返回值 0:错误的触发
u8 Check_WKUP(void)
{
	u8 t=0;
	LED0=0;
	while(1)
	{
		if(WKUP_KD)
		{
			t++;
			delay_ms(30);
			if(t>=100)
			{
				LED0=0;
				return 1;
			}
		}
		else
		{
			LED0=1;
			return 0;
		}
	}
}
void EXTI0_IRQHandler(void)
{
	EXTI_ClearITPendingBit(EXTI_Line0);// 清除 LINE10 上的中断标志位
	if(Check_WKUP())
	{
		Sys_Enter_Standby();
	}
}
void WKUP_Init(void)
{
	GPIO_InitTypeDef GPIO_ist; 
	NVIC_InitTypeDef NVIC_ist;
	EXTI_InitTypeDef EXTI_ist;
	//使能GPIOA和复用功能时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);
	GPIO_ist.GPIO_Pin=GPIO_Pin_0;//PA0
	GPIO_ist.GPIO_Mode =GPIO_Mode_IPD;//下拉输入
	GPIO_Init(GPIOA,&GPIO_ist);
	//中断线 0 连接 GPIOA.0
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
	EXTI_ist.EXTI_Line=EXTI_Line0;
	EXTI_ist.EXTI_Mode= EXTI_Mode_Interrupt; 
	EXTI_ist.EXTI_Trigger=EXTI_Trigger_Rising;
	EXTI_ist.EXTI_LineCmd= ENABLE;
	EXTI_Init(&EXTI_ist);//初始化外部中断
	
	NVIC_ist.NVIC_IRQChannel=EXTI0_IRQn;
	NVIC_ist.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_ist.NVIC_IRQChannelSubPriority=2;
	NVIC_ist.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_ist);
	if(!Check_WKUP())Sys_Standby();
}



可以看到我们设定的是3秒有效,即按下WK_UP键3秒以上才会进入待机模式(关机)然后再按3秒以上便会开机。。
可能对开机有点不大理解 我们找到关机函数中复位IO口那个函数源码
void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  if (NewState != DISABLE)
  {
    RCC->APB2RSTR |= RCC_APB2Periph;
  }
  else
  {
    RCC->APB2RSTR &= ~RCC_APB2Periph;
  }
}


因为我们传进去的第二个参数是DISABLE 所以它会执行 RCC->APB2RSTR &= ~RCC_APB2Periph;
可以看到每次都对 APB2Periph取反后按位与, 达到开关机的效果。。

wkup.h
#ifndef _WKUP_H
#define _WKUP_H
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"

#define WKUP_KD PAin(0)//PA0 检测是否外部 WK_UP 按键按下
u8 Check_WKUP(void);//检测 WKUP 脚的信号
void WKUP_Init(void);//PA0 WKUP 唤醒初始化
void Sys_Enter_Standby(void);//系统进入待机模式
#endif

主函数直接保留上一节时钟的代码(加了WKUP的初始化)。。在LCD上显示时间,按WP_UP3秒关机
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "usmart.h"
#include "rtc.h"
#include "wkup.h"
void init(void)
{
	NVIC_Configuration();
	delay_init();
	uart_init(9600);
	LED_Init();
	LCD_Init();
	WKUP_Init();
	usmart_dev.init(72);//初始化SMART组件
}
int main(void)
{
	u8 t;
	init();
  POINT_COLOR=RED;
	while(RTC_Init())		//RTC初始化	,一定要初始化成功
	{ 
		LCD_ShowString(60,130,200,16,16,"RTC ERROR!   ");	
		delay_ms(800);
		LCD_ShowString(60,130,200,16,16,"RTC Trying...");	
	}
	//显示时间
	POINT_COLOR=BLUE;//设置字体为蓝色					 
	LCD_ShowString(60,130,200,16,16,"    -  -     ");	   
	LCD_ShowString(60,162,200,16,16,"  :  :  ");	 		    
	while(1)
	{								    
		if(t!=calendar.sec)
		{
			t=calendar.sec;
			LCD_ShowNum(60,130,calendar.w_year,4,16);									  
			LCD_ShowNum(100,130,calendar.w_month,1,16);									  
			LCD_ShowNum(124,130,calendar.w_date,2,16);	 
			switch(calendar.week)
			{
				case 0:
					LCD_ShowString(60,148,200,16,16,"Sunday   ");
					break;
				case 1:
					LCD_ShowString(60,148,200,16,16,"Monday   ");
					break;
				case 2:
					LCD_ShowString(60,148,200,16,16,"Tuesday  ");
					break;
				case 3:
					LCD_ShowString(60,148,200,16,16,"Wednesday");
					break;
				case 4:
					LCD_ShowString(60,148,200,16,16,"Thursday ");
					break;
				case 5:
					LCD_ShowString(60,148,200,16,16,"Friday   ");
					break;
				case 6:
					LCD_ShowString(60,148,200,16,16,"Saturday ");
					break;  
			}
			LCD_ShowNum(60,162,calendar.hour,2,16);									  
			LCD_ShowNum(84,162,calendar.min,2,16);									  
			LCD_ShowNum(108,162,calendar.sec,2,16);
			LED0=!LED0;
		}	
		delay_ms(10);								  
	} 
}


2018-06-07 14:31:43 qq_36308229 阅读数 1471
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3395 人正在学习 去看看 朱有鹏
实验仿真图


源程序代码:(弹奏部分代码暂时去掉,见谅,需要的留言,转载请注明出处,谢谢!)


    DUAN EQU 0c000H
    WEI EQU  0a000H 
    LED0 EQU 8000H
 ORG 0000H          ;复位地址  
    LJMP MAIN          ;跳转到主程序
 ORG 0003H          ;外部中断0入口地址
 LJMP INT00    ;跳转到外部中断0服务程序
 ORG 000BH          ;T0中断入口
 LJMP TIM0          ;跳转到T0中断服务程序
       
 
 ORG 0030H          ;主程序入口地址  
MAIN:


MOV DPTR,#LED0
MOV A,#00H
MOVX @DPTR,A 
  
   
    MOV TMOD,#01H      ;写入T0控制字, 16位定时方式
 SETB IT0           ;外部中断为下降沿触发
 MOV  IE,#83H       ;开中断
 MOV  30H,#00H      ;取简谱码指针
 MOV  R6,#0FFH       ;选择音乐节奏灯循环次数
 CLR  23H           ;功能选择标志 00:键盘 01:音乐


NEXT:  CLR  TR0
        JNB  23H,KEYPLAY   ;若标志位是0则转到键盘程序
        SETB P2.2
  MOV  A,30H         ;简谱码指针装入A
        JNB P0.1,START1    ;否则查询播放哪一首歌曲   
        JNB P0.2,START2
        JNB P0.3,START3
        LJMP NEXT


;确定不同歌曲的基地址
START1:


 MOV  DPTR,#TABLE   ;从TABLE处取简谱码
 MOV 60H,DPH
 MOV 61H,DPL
 MOV A,#00H
        LJMP NEXT1
START2:


 MOV  DPTR,#TABLE2  ;从TABLE2处取简谱码
  MOV 60H,DPH
 MOV 61H,DPL
   MOV A,#01H
        LJMP NEXT1
START3:


 MOV  DPTR,#TABLE3  ;从TABLE处取简谱码
  MOV 60H,DPH
 MOV 61H,DPL
   MOV A,#02H
        LJMP NEXT1


;键盘弹奏程序入口
KEYPLAY:    ;键盘程序入口
    SETB P2.1
 CLR P2.2
 JNB P0.4,LOWTONE     ;查询是高音还是其他的音
 JNB P0.5,MIDDLETONE
 JNB P0.6,HIGHTONE
 LJMP NEXT           ;没有选择高中低音则重新查询




;确定高中低音基地址
LOWTONE:
 MOV DPTR,#LOWTABLE   ;赋基地址值
 MOV 50H,DPH
 MOV 51H,DPL
 LJMP KEY      ;跳转到按键查询程序


MIDDLETONE:
        MOV DPTR,#MIDDLETABLE
  MOV 50H,DPH
 MOV 51H,DPL
 LJMP KEY


HIGHTONE: 
  MOV DPTR,#HIGHTABLE
  MOV 50H,DPH
 MOV 51H,DPL
  LJMP KEY




;歌曲播放程序
NEXT1: MOV DPTR,#SEG7
   MOVC A,@A+DPTR
  MOV DPTR,#DUAN
     MOVX @DPTR,A
     MOV DPTR,#WEI
 MOV A,#000BH
    MOVX @DPTR,A
    MOV DPH,60H
 MOV DPL,61H
 MOV A,30H
    MOVC A,@A+DPTR
 MOV  R2,A          ;取得的简谱码暂存于R2
 JZ   END0          ;是否取到结束码00H
 ANL  A,#0FH        ;不是,则取节拍码
 MOV  R5,A          ;节拍码存于R5
 MOV  A,R2          ;将简谱码装入A
 SWAP A             ;高、低4位交换
 ANL  A,#0FH        ;取音符码
 JNZ  SING          ;取得的音符码是否为0?
 CLR  TR0           ;是则不发音
 lJMP  D1           ;跳转到D1


SING:   DEC  A             ;取得的音符码减1(不含0)
 MOV  22H,A         ;存入22H单元
 RL   A             ;乘2
 MOV  DPTR,#TABLE1  ;到TABLE1中取相对的高位字节值
 MOVC A,@A+DPTR
 MOV  TH0,A         ;取得的高位字节装入TH0和21H单元
 MOV  21H,A
 MOV  A,22H         ;再装入取得的音符码
        Rl   A             ;乘2
 INC  A             ;加1
 MOVC A,@A+DPTR     ;到TABLE1中取相对的低位字节值
 MOV  TL0,A         ;取得的高位字节装入TL0和20H单元
 MOV  20H,A
 SETB TR0           ;启动T0
D1:     LCALL DELAY        ;基本单位时间1/4拍,延时187毫秒
 INC  30H           ;取简谱码指针加1
 LJMP NEXT          ;取下一个码
END0:   CLR  TR0           ;停止T0
 CLR 30H            ;清零简朴指针
 LJMP NEXT          ;重复循环
2015-11-26 18:17:26 chengdong1314 阅读数 586
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3395 人正在学习 去看看 朱有鹏

这篇文章讲51芯片内部各个模块的汇编程序,这里不做实验,只贴代码:

串口工作方式1-汇编:

中断地址定义:

  ORG 0000H  ;伪指令 告诉编译器从0000H开始
  LJMP MAIN  ;64KB无条件跳转 跳转到main处执行
  ORG 0003H     ;外部中断0中断入口
  LJMP exter0
  ORG 000BH     ;T0溢出中断入口
  LJMP time_0  
  ORG 0013H     ;外部中断1中断入口
  LJMP exter1  
  ORG 001BH     ;T1溢出中断入口
  LJMP time_1
  ORG 0023H     ;串口中断入口
  LJMP USART_INT
  ORG 0100H  ;虽然这里是伪指令 但是确实有标明地址的作用


main:

MAIN:
  MOV SP,#3FH   ;设置栈低为5FH
  MOV num,#00H
  MOV wei,#07H
  MOV SCON,#50H
  MOV TMOD,#21H   //定时器0刷数码管 定时器1
  MOV TH1,#0FDH  //自动从装载
  MOV TL1,#0FDH
  SETB TR1  ;定时器1开始
  SETB ES  ;开定串口中断
  SETB PS    ;串口中断优先级为高
  MOV TH0,#0FFH
  MOV TL0,#000H
  SETB ET0   ;开定时中断
  CLR PT0    ;设置定时器0的中断优先级为低
  SETB TR0   ;开启定时器
  SETB EA      ;开总中断
  MOV num1,#00H  ;初始化数据
  MOV num2,#00H
  LCALL led_Static_display  ;数码管初始化
  ;********************死循环**********************

中断程序:

USART_INT:       
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  JNB RI,OVERUSART_INT  ;接收中断
  CLR RI  ;手动清除
  MOV UARTTEMP,SBUF
  MOV SBUF,UARTTEMP
  MOV LEDTEMP,UARTTEMP
  JNB TI,$
  CLR TI  ;手动清除  
  OVERUSART_INT:
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  RETI        ;中断结束返回




整个程序源代码:

  ;-----------------------数码管脚功能定义---------------------------   
  LED_wei EQU P2
  LED138_0 EQU P2.0
  LED138_1 EQU P2.1
  LED138_2 EQU P2.2
  LED_duan EQU P0
  LED_P EQU P1
  ;-------------------- 数码要显示的位、数据---------------------------
  wei EQU 30H    ;数码管位选
  num EQU 31H    ;数码管段选
  num1 EQU 32H    ;定时器0进中断数
  num2 EQU 33H    ;定时器1进中断数
  UARTTEMP EQU 34H    ;串口数据
  LEDTEMP EQU 35H    ;数码管数据
  ;-----------------------------------------------
  ORG 0000H  ;伪指令 告诉编译器从0000H开始
  LJMP MAIN  ;64KB无条件跳转 跳转到main处执行
  ORG 0003H     ;外部中断0中断入口
  LJMP exter0
  ORG 000BH     ;T0溢出中断入口
  LJMP time_0  
  ORG 0013H     ;外部中断1中断入口
  LJMP exter1  
  ORG 001BH     ;T1溢出中断入口
  LJMP time_1
  ORG 0023H     ;串口中断入口
  LJMP USART_INT
  ORG 0100H  ;虽然这里是伪指令 但是确实有标明地址的作用
  ;-----------------------------------------------
MAIN:
  MOV SP,#3FH   ;设置栈低为5FH
  MOV num,#00H
  MOV wei,#07H
  MOV SCON,#50H
  MOV TMOD,#21H   //定时器0刷数码管 定时器1
  MOV TH1,#0FDH  //自动从装载
  MOV TL1,#0FDH
  SETB TR1  ;定时器1开始
  SETB ES  ;开定串口中断
  SETB PS    ;串口中断优先级为高
  MOV TH0,#0FFH
  MOV TL0,#000H
  SETB ET0   ;开定时中断
  CLR PT0    ;设置定时器0的中断优先级为低
  SETB TR0   ;开启定时器
  SETB EA      ;开总中断
  MOV num1,#00H  ;初始化数据
  MOV num2,#00H
  LCALL led_Static_display  ;数码管初始化
  ;********************死循环**********************
while1:
 
  LJMP while1
  ;================================================
  ;外部中断0函数
  ;================================================
exter0:    
  RETI        ;中断结束返回
  ;================================================
  ;外部中断1函数
  ;================================================
exter1:    
  RETI        ;中断结束返回
  ;================================================
  ;定时器0中断函数
  ;================================================
time_0:       
  PUSH 07H
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  MOV TH0,#0FFH
  MOV TL0,#000H
  INC num1
  MOV A,num1
  CJNE A,#01, OVERtime_0
  MOV num1,#00H
  MOV 07H,#10H
  FOR:
  MOV num,LEDTEMP  ;显示串口数据
  ANL num,#0FH  ;低位
  MOV wei,#07H
  LCALL led_Static_display
  LCALL DELAY1ms
  MOV num,LEDTEMP  
  ANL num,#0F0H   ;高位
  MOV A,num
  RR A
  RR A
  RR A
  RR A
  MOV num,A
  MOV wei,#06H
  LCALL led_Static_display
  LCALL DELAY1ms
  DJNZ 07H,FOR
  OVERtime_0:
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  POP 07H
  RETI        ;中断结束返回
  ;================================================
  ;定时器1中断函数
  ;================================================
time_1:       

  RETI        ;中断结束返回
  ;================================================
  ;定时器1中断函数
  ;================================================
USART_INT:       
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  JNB RI,OVERUSART_INT  ;接收中断
  CLR RI  ;手动清除
  MOV UARTTEMP,SBUF
  MOV SBUF,UARTTEMP
  MOV LEDTEMP,UARTTEMP
  JNB TI,$
  CLR TI  ;手动清除  
  OVERUSART_INT:
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  RETI        ;中断结束返回
  ;================================================
  ;数码管静态显示函数
  ;================================================
led_Static_display:
  ANL wei, #07H
  MOV A,#078H
  ANL A,LED_wei
  ORL A, wei
  MOV wei,A
  MOV A,num  
  MOV DPTR,#numtab
  MOVC A,@A+DPTR  ;查表取数据
  MOV LED_wei,wei
  MOV LED_duan,A
  RET
  ;================================================
  ;各种参数的延时子函数
  ;================================================
DELAY100us:     ;100us  
  MOV R6,#06H
  DEL11: MOV R7,#08H
  DEL12: DJNZ R7,DEL12
  DJNZ R6,DEL11
  RET

DELAY500us:    ;500us
  MOV R6,#0CH   ;288
  DEL21: MOV R7,#18H
  DEL22: DJNZ R7,DEL22
  DJNZ R6,DEL21
  RET
 
DELAY1ms:    ;1ms
  MOV R6,#18H   
  DEL61: MOV R7,#18H
  DEL62: DJNZ R7,DEL62
  DJNZ R6,DEL61
  RET

DELAY40ms:    ;延时40ms  500得1ms
  MOV R6,#100
  DEL41: MOV R7,#200
  DEL42: DJNZ R7,DEL42
  DJNZ R6,DEL41
  RET

DELAY256ms:        ;延时256ms
  MOV R5,#05H
  DEL51: MOV R6,#100
  DEL52: MOV R7,#0FFH
  DEL53: DJNZ R7,DEL53
  DJNZ R6,DEL52
  DJNZ R5,DEL51
  RET
 
DELAY500ms:        ;延时256ms
  MOV R5,#0AH
  DEL81: MOV R6,#100
  DEL82: MOV R7,#0FFH
  DEL83: DJNZ R7,DEL83
  DJNZ R6,DEL82
  DJNZ R5,DEL81
  RET
 
DELAY1s:    ;1秒
  MOV R5,#16H
  DEL31: MOV R6,#100
  DEL32: MOV R7,#0FFH
  DEL33: DJNZ R7,DEL33
  DJNZ R6,DEL32
  DJNZ R5,DEL31
  RET
 
DELAY10s:    ;10秒
  MOV R5,#0DCH
  DEL71: MOV R6,#100
  DEL72: MOV R7,#0FFH
  DEL73: DJNZ R7,DEL73
  DJNZ R6,DEL72
  DJNZ R5,DEL71
  RET
numtab: DB  03FH,006H,05BH,04FH,066H,06DH,07DH,007H,07FH,06FH,077H,07CH,039H,05EH,079H,071H,000H
end

keil工程整体源码:

串口工作方式1-汇编

http://download.csdn.net/detail/chengdong1314/9303147


2015-11-26 21:28:29 chengdong1314 阅读数 1038
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

    3395 人正在学习 去看看 朱有鹏

这篇文章讲51芯片内部各个模块的汇编程序,这里不做实验,只贴代码:

定时器模块程序:

中断地址,中断调用:

  ;-----------------------------------------------
  ORG 0000H  ;伪指令 告诉编译器从0000H开始
  LJMP MAIN  ;64KB无条件跳转 跳转到main处执行
  ORG 0003H     ;外部中断0中断入口
  LJMP exter0
  ORG 000BH     ;T0溢出中断入口
  LJMP time_0  
  ORG 0013H     ;外部中断1中断入口
  LJMP exter1  
  ORG 001BH     ;T1溢出中断入口
  LJMP time_1
  ORG 0100H  ;虽然这里是伪指令 但是确实有标明地址的作用
  ;-----------------------------------------------



主函数 main:

MAIN:
  MOV SP,#3FH   ;设置栈低为5FH
  MOV num,#00H
  MOV wei,#07H
  MOV TMOD,#11H
  MOV TH0,#4CH
  MOV TL0,#00H
  MOV TH1,#4CH
  MOV TL1,#00H
  SETB ET0   ;开定时中断
  CLR PT0    ;设置定时器0的中断优先级为低
  SETB TR0   ;开启定时器
  SETB ET1
  SETB PT1
  SETB TR1
  SETB EA      ;开总中断
  MOV num1,#00H  ;初始化数据
  MOV num2,#00H
  MOV LEDTEMP,#0FEH
  LCALL led_Static_display  ;数码管初始化
  ;********************死循环**********************



中断函数:

  ;================================================
  ;定时器0中断函数
  ;================================================
time_0:       
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  MOV TH0,#4CH
  MOV TL0,#00H
  INC num1
  MOV A,num1
  CJNE A,#020, OVERtime_0
  INC num
  MOV A,num
  CJNE A,#010H,rigthnumtime_0
  MOV num,#00H
  rigthnumtime_0:
  LCALL led_Static_display
  MOV num1,#00H
  OVERtime_0:
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  RETI        ;中断结束返回
  ;================================================
  ;定时器1中断函数
  ;================================================
time_1:       
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  MOV TH1,#4CH
  MOV TL1,#00H
  INC num2
  MOV A,num2
  CJNE A,#02H, OVERtime_1
  MOV A,LEDTEMP
  RR A
  MOV LEDTEMP,A
  MOV LED_P,LEDTEMP
  MOV num2,#00H
  OVERtime_1:
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  RETI        ;中断结束返回
  ;================================================
  ;数码管静态显示函数
  ;================================================



整个程序的代码:

  ;-----------------------数码管脚功能定义---------------------------   
  LED_wei EQU P2
  LED138_0 EQU P2.0
  LED138_1 EQU P2.1
  LED138_2 EQU P2.2
  LED_duan EQU P0
  LED_P EQU P1
  ;-------------------- 数码要显示的位、数据---------------------------
  wei EQU 30H    ;数码管位选
  num EQU 31H    ;数码管段选
  num1 EQU 32H    ;定时器0进中断数
  num2 EQU 33H    ;定时器1进中断数
  LEDTEMP EQU 34H    ;小灯数据暂存
  ;-----------------------------------------------
  ORG 0000H  ;伪指令 告诉编译器从0000H开始
  LJMP MAIN  ;64KB无条件跳转 跳转到main处执行
  ORG 0003H     ;外部中断0中断入口
  LJMP exter0
  ORG 000BH     ;T0溢出中断入口
  LJMP time_0  
  ORG 0013H     ;外部中断1中断入口
  LJMP exter1  
  ORG 001BH     ;T1溢出中断入口
  LJMP time_1
  ORG 0100H  ;虽然这里是伪指令 但是确实有标明地址的作用
  ;-----------------------------------------------
MAIN:
  MOV SP,#3FH   ;设置栈低为5FH
  MOV num,#00H
  MOV wei,#07H
  MOV TMOD,#11H
  MOV TH0,#4CH
  MOV TL0,#00H
  MOV TH1,#4CH
  MOV TL1,#00H
  SETB ET0   ;开定时中断
  CLR PT0    ;设置定时器0的中断优先级为低
  SETB TR0   ;开启定时器
  SETB ET1
  SETB PT1
  SETB TR1
  SETB EA      ;开总中断
  MOV num1,#00H  ;初始化数据
  MOV num2,#00H
  MOV LEDTEMP,#0FEH
  LCALL led_Static_display  ;数码管初始化
  ;********************死循环**********************
while1:
  LJMP while1
  ;================================================
  ;外部中断0函数
  ;================================================
exter0:    
  RETI        ;中断结束返回
  ;================================================
  ;外部中断1函数
  ;================================================
exter1:    
  RETI        ;中断结束返回
  ;================================================
  ;定时器0中断函数
  ;================================================
time_0:       
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  MOV TH0,#4CH
  MOV TL0,#00H
  INC num1
  MOV A,num1
  CJNE A,#020, OVERtime_0
  INC num
  MOV A,num
  CJNE A,#010H,rigthnumtime_0
  MOV num,#00H
  rigthnumtime_0:
  LCALL led_Static_display
  MOV num1,#00H
  OVERtime_0:
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  RETI        ;中断结束返回
  ;================================================
  ;定时器1中断函数
  ;================================================
time_1:       
  PUSH DPH
  PUSH DPL
  PUSH PSW
  PUSH ACC
  MOV TH1,#4CH
  MOV TL1,#00H
  INC num2
  MOV A,num2
  CJNE A,#02H, OVERtime_1
  MOV A,LEDTEMP
  RR A
  MOV LEDTEMP,A
  MOV LED_P,LEDTEMP
  MOV num2,#00H
  OVERtime_1:
  POP ACC
  POP PSW
  POP DPL
  POP DPH
  RETI        ;中断结束返回
  ;================================================
  ;数码管静态显示函数
  ;================================================
led_Static_display:
  ANL wei, #07H
  ANL LED_wei,#0F8H
  MOV A,wei
  ORL LED_wei,A
  MOV A,num  
  MOV DPTR,#numtab
  MOVC A,@A+DPTR  ;查表取数据
  MOV LED_duan,A
  RET
  ;================================================
  ;各种参数的延时子函数
  ;================================================
DELAY100us:     ;100us  
  MOV R6,#06H
  DEL11: MOV R7,#08H
  DEL12: DJNZ R7,DEL12
  DJNZ R6,DEL11
  RET

DELAY500us:    ;500us
  MOV R6,#0CH   ;288
  DEL21: MOV R7,#18H
  DEL22: DJNZ R7,DEL22
  DJNZ R6,DEL21
  RET
 
DELAY1ms:    ;1ms
  MOV R6,#18H   
  DEL61: MOV R7,#18H
  DEL62: DJNZ R7,DEL62
  DJNZ R6,DEL61
  RET

DELAY40ms:    ;延时40ms  500得1ms
  MOV R6,#100
  DEL41: MOV R7,#200
  DEL42: DJNZ R7,DEL42
  DJNZ R6,DEL41
  RET

DELAY256ms:        ;延时256ms
  MOV R5,#05H
  DEL51: MOV R6,#100
  DEL52: MOV R7,#0FFH
  DEL53: DJNZ R7,DEL53
  DJNZ R6,DEL52
  DJNZ R5,DEL51
  RET
 
DELAY500ms:        ;延时256ms
  MOV R5,#0AH
  DEL81: MOV R6,#100
  DEL82: MOV R7,#0FFH
  DEL83: DJNZ R7,DEL83
  DJNZ R6,DEL82
  DJNZ R5,DEL81
  RET
 
DELAY1s:    ;1秒
  MOV R5,#16H
  DEL31: MOV R6,#100
  DEL32: MOV R7,#0FFH
  DEL33: DJNZ R7,DEL33
  DJNZ R6,DEL32
  DJNZ R5,DEL31
  RET
 
DELAY10s:    ;10秒
  MOV R5,#0DCH
  DEL71: MOV R6,#100
  DEL72: MOV R7,#0FFH
  DEL73: DJNZ R7,DEL73
  DJNZ R6,DEL72
  DJNZ R5,DEL71
  RET
numtab: DB  03FH,006H,05BH,04FH,066H,06DH,07DH,007H,07FH,06FH,077H,07CH,039H,05EH,079H,071H,000H
end

keil工程整体源码:

keil工程整体源码:

51汇编之双定时器数码管流水灯-汇编

http://download.csdn.net/detail/chengdong1314/9303613

没有更多推荐了,返回首页