Posts Tagged ‘单片机’

November 24, 2009

  本程序利用PIC18单片机实现了对EEPROM的读写。应用背景是”汽车里程表”,简单介绍下程序功能和流程。
  单片机接受来自RA4管脚的计数脉冲信号,应用中这个脉冲信号通常由一个传感器来产生,计数脉冲被设定为上升沿触发。计数器溢出时,需要更新一个用于存储当前里程的RAM寄存器单元COUNT,可以理解为车轮转了一定圈数后,里程表的增加一定的里程数。
  RB0管脚用来接收一个外部中断信号,接收到中断信号后,在中断服务程序中将COUNT的值即当前里程数保存至EEPROM的00H单元。这样可以配合外部电路实现当单片机掉电时自动保存里程表数值的功能,即汽车熄火时保存里程表,以减少对EEPROM的读写次数。
  单片机启动时,首先应该到EEPROM的相应单元读取里程表的当前值,并在此基础上进行累加。
  程序中为了调试方便,还将COUNT的数值同步地通过8个LED以二进制形式较直观地显示了出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
LOOP	
 
	BCF	INTCON, T0IF 	; 清TMR0中断标志
	MOVLW	TMR0B 
	MOVWF	TMR0L 		; 装入计数初值 253
	BSF	T0CON, TMR0ON 	; 启动计数器
	TEST	
	BTFSS	INTCON, T0IF 	; 检测TMR0是否溢出
	GOTO	TEST
	INCF	COUNT, F 	; 计数加一
	MOVFF	COUNT, PORTD 	; 输出,显示
 
	GOTO	LOOP
 
WIRT_EE				; 写EEPROM
	BCF	EECON1, EEPGD
	BCF	EECON1, CFGS 	; 设定EECON1控制寄存器
	BSF	EECON1, WREN 	; EEPROM写使能
	BCF	INTCON, GIE 	; 写EEPROM时需要关闭一切中断
Tags: ,.
November 18, 2009

  使用PIC18单片机的ADC转换模块对RA0口输入的模拟电压信号进行转换,然后通过PORTD端口输出,而这里与PORTD对应引脚相连接的是8个LED。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
list P = 18F452 ;指明单片机型号为PIC18F452
#include P18F452.INC ;包含一个头文件,其中定义了一些端口及一些特殊寄存器的地址
 
	org	0000h  	;PIC上电时从0000h单元开始执行
	goto	main  	;跳转到主程序
	ORG	0008H  	;中断向量入口
	BTFSS	PIR1, ADIF 	; AD转换完成中断
	RETFIE
	GOTO	AD_ISR
 
	ORG	0030H  	;主程序定位
MAIN
	CLRF	TRISD  	;设定D口方向为输出
	CLRF 	PORTD 	;设定C口方向为输出
	BSF 	TRISA, 0 	; 使用AN0输入
	MOVLW	81H 	;FOSC/32, AN0, 开启
	MOVWF	ADCON0
	MOVLW	0EH 	;左对齐,AN0为模拟输入
	MOVWF	ADCON1 	;VDD & VSS为参考电压
	BCF 	INTCON, TMR0IF
	BCF 	PIR1, ADIF 	;清AD中断标志位
	BSF 	PIE1, ADIE 	;开AD中断
	BSF 	INTCON, PEIE 	;开外围中断
	BSF  	NTCON, GIE 	;开总中断
	MOVLW 	C7H 	;TMR0 8位,分频比为1:256
	MOVWF	T0CON
LOOP
	CALL	DELAY
	BSF  	DCON0, GO 	;开启 A/D转换
	GOTO	LOOP
 
DELAY
 
	BTFSS  	NTCON, TMR0IF 	; 等待延时,采样保持
	GOTO  	DELAY
	BCF  	NTCON, TMR0IF
	RETURN
 
AD_ISR ;AD转换完成时调用的中断服务程序,将转换结果输出
	ORG 	0200H
	MOVFF	ADRESH, PORTD 	;显示转换结果
	BCF 	PIR1, ADIF 	;清AD中断标志位
	RETFIE
END 	;程序结束
Tags: ,.
November 4, 2009

  PIC的汇编实在诡异,有点被颠覆的感觉,原来汇编指令还可以这么来设计,原来汇编指令怎么设计都可以。最OOXX的一条指令就一个实现短转移的指令叫做BRA,意为BRAanch,看到这条指令的时候,我都诧异了,奶罩能做什么?哇塞!居然还能跳转!?奶罩居然可以无条件跳转?!Orz……另外PIC指令把单词缩写运用的淋漓尽致,譬如指令BTFSS,是一条位测试加条件跳转指令:BTFSS = Bit + Test + FileRegister + Skip + Set,用法:BTFSS R1, 0003h, 寄存器R1的第3位为1时跳过下一条指令。真是震撼!

  最后附上PIC18的中断体系硬件结构图,出自陈育斌老师的手笔:

Tags: ,.
October 27, 2009

  图示是PIC 18单片机中定时/计数器的结构图,PIC18是一种8位的单片机,但它的定时/计数器(的寄存器)却是16位的,所以为其装初值的时候就要分高低字节分别装载。于是问题就来了,由于定时计数器一般是连续工作,需要经常进行重装,如果对一个正在工作的定时计数器进行重装的话,就会产生高低字节不同步的状态,这是一种潜在的错误,尽管这种错误发生的概率很小。为了防止这种错误的发生,PIC单片机设计者采用了上图所示的双缓存结构。其中,TMR0H’和TMR0L组成了一个真正的定时计数器,而TMR0H是一个临时寄存器只有TMR0L的写信号有效时它才能被装入TMR0H’。当需要重装定时器时,首先应该将16位定时/计数的初值的高8位装入TMR0H临时寄存器,然后在向TMR0L写入低8位时由于TMR0L写信号有效,TMR0H也被同步地装入TMR0H’。这样,定时计算器就可以正确的工作,这就是硬件的双缓冲。

Tags: ,.
May 6, 2009
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
;#################################################################
;              这是一个键盘扫描程序 
;将得到的健值(01H-10H)在右边两位数码管显示 (data= XX) 
;程序采用中断结构,硬件连接上将INT_KEY信号与P3.2(INT0) 连接;
;普通的I2C通讯程序可以直接利用,为读数据子程序需要加延时
;这是ZLG7290芯片在读数据时有延时,在RDBYT中添加一个20US延时
;#################################################################
SDA		BIT	P1.0
SCL		BIT	P1.1  
WSLA		EQU	070H
RSLA		EQU	071H
DISDA		EQU	20H		;源数据块首地址
DISCON		EQU	08H		;写入数据个数		
DATA_1		EQU	30H		;变量区首地址
;********************************************************
	ORG	8000H 
	LJMP	8100H  
;********************************************************
Tags: ,.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
 
	dat 	bit p3.2	;定义端口号
	clk	bit p3.3	
	cs	bit p3.4
 
	org	8000h		;程序定位及跳转指令的设置
	ljmp	8100h
	org	8100h
 
start:
	mov	sp, #60h	;定义堆栈底位置
stable:
	mov	r3, #00h	;循环体执行次数:256
	mov	r6, #00h	;寄存器清零
	mov	r7, #00h	;寄存器清零
loop:
				;取平均值主要是为了减小
				;高速模数转换干扰产生的误差
	lcall	tlc549_adc	;调用模数转换子程序
	add	a, r6		;向R7-R6累加a的值256次
	mov	r6, a
	mov 	a, #00h
	addc	a, r7
	mov	r7, a	
	lcall	delay
	djnz	r3, loop
	mov	a, r7		;将R7中的平均值送到a
	cpl	a		;a取反
	mov	p1, a		;输出a的值
	sjmp	stable
 
tlc549_adc:			;模数转换的驱动子程序
	push	07h
	clr	a		;清零
	clr	clk		;清零
	mov	r7, #08h	;由于是串行输入,每字节需要8次读入
	clr	cs		;片选信号置低位,选中模数转换器
loop1:
	setb	clk		;开始读取数据
	mov	c, dat
	rlc	a		;诸位读取,送到a
	clr	clk
	djnz	r7, loop1
	setb	cs
	setb	clk
	pop	07h
ret
 
delay:				;微小的延时,用来同步和协调单片机
				;与模数转换器的工作步调
	push	00h
	mov	r0, #00h
	djnz	r0, $
	pop	00h
ret
 
 
end
Tags: ,.
April 29, 2009

功能描述

功能很简单,程序更简单:

简单的蜂鸣器实验程序:本程序通过在P1.1输出一个音频范围的方波,驱动实验板上的蜂鸣器发出蜂鸣声,其中包含有一个定时模块,作用是使输出的方波频率在人耳朵听觉能力之内的20KHZ以下,如果没有这个延时程序的话,输出的频率将大大超出人耳朵的听觉能力,我们将不能听到声音。更改定时常数,可以改变输出频率,也就可以调整蜂鸣器的音调。

Tags: ,.

功能描述

由p1口外接按键开关,p3.3接蜂鸣器组成。

1
2
3
4
5
6
7
8
9
 	org 	8000h		;定位
	ljmp 	start
	org 	8100h
start:
	mov 	sp, #60h
	mov	tmod, #10h	;置T1为方式1
;	mov	tl1, #010h
;	mov	th1, #010h	;设初值,定时为50ms
	setb	tr1		;启动定时器T1
Tags: ,.

功能描述

正常情况下(p3.2为高电平), p3.3的电平以一定的频率连续翻转,当p3.2为低电平时,触发int0外部中断,进入中断服务程序,另p3.3保持低电平,并将p1端口加1。p3.2外接一个按键开关时,中断服务程序有防抖动的功能,这时通过一定的延时(通常为10ms–20ms)来实现的。

程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 	org 	8000h		;定位
	ljmp 	start
	org 	8003h		;中断向量
	ljmp	int_0
	org 	8100h
start:
	mov 	sp, #60h
	setb	ex0		;开int0中断
	setb 	ea		;开总中断
	mov	tcon, #00h	;低电平触发
	mov	r3, #00h
	mov	a, r3
	cpl	a
loop3:				;死循环
	mov	p1, a
	cpl	p3.3		;翻转
	lcall	DELAY		;延时
	sjmp	loop3
 
int_0:				;中断服务子程序
	push	psw
	lcall	DELAY		;防抖动
	setb	p3.3
	inc	r3
	mov	a, r3
	cpl	a
	mov	p1, a
	jnb	p3.2, $		;查询,防止多次中断
	lcall	DELAY		;还是防抖动
	pop	psw
	reti
 
DELAY:  PUSH 06H
	PUSH 07H
	MOV R7, #70H
LABEL1:
	MOV R6, #70H
LABEL2:
	DJNZ R6, $
	DJNZ R7, LABEL1
	POP 07H
	POP 06H
	RET
	END
Tags: ,.

89C51单片机,每计时一秒将P1端口翻转一次,晶振频率12MHz,中断方式实现。这里另外一个查询方式的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 	org 	8000h		;定位
	ljmp 	start
	org 	801bh		;中断向量
	ljmp	int_t1
	org 	8100h
start:
	mov 	sp, #60h
	mov	tmod, #10h	;置T1为方式1
	mov	tl1, 0fch
	mov	th1, #4bh	;设初值,定时为50ms
	mov	r1, #20		;中断次数,以使定时为1ms
	setb	tr1		;启动定时器T1
	clr	a		;累加器清零
	setb	et1		;T1中断允许
	setb	ea		;开总外部中断标志
	sjmp	$		;等待中断
 
 
int_t1:				;中断服务子程序
	push	psw		;保存程序状态字
	mov 	tl1, #0fch	;重装计数器
	mov	th1, #4bh
	djnz	r1, exit	;1s时间未到,返回主程序,等待下一次中断
	mov	r1, #20		;1s时间到,重装r1
	cpl	a		;a取反
	mov	p1, a		;输出a
exit:	pop	psw		;程序状态字出栈
	reti
 
DELAY:  PUSH 06H
	PUSH 07H
	MOV R7, #70H
LABEL1:
	MOV R6, #70H
LABEL2:
	DJNZ R6, $
	DJNZ R7, LABEL1
	POP 07H
	POP 06H
	RET
	END
Tags: ,.
Page 1 of 212Next