http://www.erji.net/attachment/Mon_0711/6_37069_779f0b1f6439f9f.jpg
http://www.erji.net/attachment/Mon_0711/6_37069_69caf553195365f.jpg
http://www.erji.net/attachment/Mon_0711/6_37069_31efc857fe02311.jpg
【关键词】:串行同步、LCD模块
SPI(Serial Peripheral Interface)是串行同步接口的简称,在MCU中它可以方便的连接多个采用SPI通信协议的外围芯片或另外的MCU,实现在短距离内的高速同步通信。由于其连接简单,通信速度快,近年来在音响控制中已经获得广泛应用。
SPI模式允许同时同步发送和接收 8位数据。支持SPI的四种工作模式。
通常用以下三个引脚来完成通信:
◎串行数据输出(SDO)
◎串行数据输入(SDI)
◎串行时钟(SCK)
当工作在从动模式时,可能还需要第4个引脚:
◎从动选择(SS)
SSP 模块由一个发送/ 接收移位寄存器(SSPSR)和一个缓冲寄存器(SSPBUF)组成。 SSPSR
用于器件输入和输出数据的移位,最高有效位在前。 在新的数据接收完毕前,SSPBUF 保存写入
SSPSR 的数据。一旦8 位新数据接收完毕,该字节被送入 SSPBUF 寄存器。同时缓冲区满标志
位 BF(SSPSTAT 0)和中断标志位 SSPIF 置1。
当SSPBUF 中的数据被读出后,BF 位即被清零。如果 SPI 仅仅作为一个发送器,则不必理会接收的
数据。 通常可用SSP 中断来判断发送或接收是否完成。如果不使用中断来处理数据的收发,用软件查询方法同样可确保不会发生写冲突。
要使能SSP 串行口, 必须将SSP 使能位SSPEN 位(SSPCON5)置位。要复位或重新配置
SPI模式,先将 SSPEN 位清零,对 SSPCON重新初始化,然后把 SSPEN位置1。这将设定 SDI、
SDO、SCK 和 SS 引脚为SSP 串行口引脚。要将这些引脚用于串行口功能,还必须通过TRIS 寄
存器设置正确的方向,即:
◎SDI 定义成输入
◎SDO 定义成输出
◎主控模式时, SCK 定义成输出
◎从动模式时, SCK 定义成输入
◎SS 定义成输入
当需要对多个SPI外围芯片进行控制时,还需要相应的“片选”控制信号,以便使得多个并联在SPI总线上的芯片知道是否是呼叫自己。
SPI工作在主动模式时,它的SCK会发出一串时钟脉冲串,当数据数据发送时,就在这些脉冲的同步下,从SDO引脚输出;当数据接收时,这个时钟脉冲串也是从动器件向主模块发送数据的时钟,由主动器件的SDI引脚接收,从动器件自己不会发出SCK时钟脉冲。
下面我们用一块带SPI接口总线的LCD显示模块:LM3033B-0BR3连接,该模块内部有中英文字库,可以显示128x64的点阵,对LCD模块作了必要的初始化后,把ASCII码数据送到SPI总线,就可以实现数据显示(电路连接请参见图5.1,实物请参见图5.2、5.3)。
实验例程如下:
================================================
TITLE SPI_DEMO PROGRAM
(C) copyright by Little Dot CO,.LTD.
DESIGN DATE BEGIN: 2007/11/19
FINISH: 2007/11/20 (V1.0)
Programan: My
=================================================
本程序是一个演示MCU通过SPI和液晶显示模块连接的示范程序,
当程序运行时,会在MCU定时中断的控制下每隔300mS向LCD模块
传送一下数据,会显示出中文:
“欢迎进入SPI通信实验!”
list p=16f873A
#include
***********************************************
* Variable definitions *
***********************************************
以下为常量赋值:
CS EQU .4 PORTC 4 LCD的片选控制
UPDATE EQU .30 刷新显示的30mS定时数据
TMR_COUNT EQU .217 Timer Reload value: 39X256=10 mS
基本定时时间为:10 mS 中断一次。
================================================
以下为变量定义:
W_TEMP EQU 0X20
STATUS_TEMP EQU 0X21
TIMER EQU 0X22
DIS_COMD EQU 0X23
DIS_DATA EQU 0X24
DELAY_100 EQU 0X25
CLEAR_X EQU 0X26
SEND_DATA EQU 0X27
================================================
ORG 0X00 程序的复位入口
NOP
GOTO INIT_START
ORG 0X04 程序的定时中断入口
GOTO TIMER_INT
ORG 0X07
INIT_START
CLRF PORTA
BSF STATUS,RP0
MOVLW B00111100 RA2-4 INPUT
MOVWF TRISA
MOVLW B10000110 Select all digital
MOVWF ADCON1
BCF STATUS,RP0
CLRF PORTB
BSF STATUS,RP0
MOVLW B11110000 RB0-3 OUTPUT
MOVWF TRISB
BCF STATUS,RP0
CLRF PORTC
BSF STATUS,RP0
MOVLW B00000000 RC ALL OUTPUT
MOVWF TRISC
BCF STATUS,RP0
MOVLW #UPDATE
MOVWF TIMER 给300 mS定时器赋值
SPI_SET
MOVLW B01000000 CKE=0 (bit 6) 设置SPI的模式
BSF STATUS,RP0
MOVWF SSPSTAT
BCF STATUS,RP0
MOVLW B00000010 CKP=1 (bit 4)
MOVWF SSPCON 1/64(01:1/16) osc 设置SPI的通信速率
BSF SSPCON,SSPEN SPI通信允许
TIMER_SET
MOVLW TMR_COUNT TMR_COUNT 是一个常量,用来给定时器0赋值
MOVWF TMR0 BASIC TIMER = 10 mS
BSF STATUS,RP0
MOVLW B00000111 T0 X 256 设定预分频系数为:每当时钟计数256次,计数器TMR0就加一
MOVWF OPTION_REG 因为常量TMR_COUNT=217,当增加了39次以后,定时器0就从256(FFH)
BCF STATUS,RP0 溢出变为0,这时候就产生一次中断,中断的时间:
1 uS (硬件对4MHZ石英晶体的4分频) X 256 X 39 = 9984 uS 约等于10 mS
BSF INTCON,T0IE 允许定时器0中断
BSF INTCON,GIE 开总中断位(这是所有中断的总控制位)
========================================
Main_Loop: 主循环开始
NOP
在本例程中,主循环实际上是一个空循环,只是在这里等待定时中断
到来,然后向LCD刷新数据
goto Main_Loop 返回主循环开始处
========================================
定时中断服务子程序
========================================
TIMER_INT:
MOVWF W_TEMP 把W寄存器保存起来,以备中断完成后恢复现场
SWAPF STATUS,W
BCF STATUS,RP0 把状态寄存器保存起来,以备中断完成后恢复现场
MOVWF STATUS_TEMP PUSH
BCF INTCON,T0IE 关闭定时中断允许控制位
MOVLW TMR_COUNT 重新载入基本定时的数据(设定计数的次数)
MOVWF TMR0 BASIC TIMER = 10 mS
DECFSZ TIMER,F 每中断一次定时计数器减去1
GOTO TI_EX 如果不等于0,则退出中断服务子程序
MOVLW #UPDATE 如果=0,则重新给定时计数器赋值
MOVWF TIMER
CALL DISPLAY 调用LCD模块显示程序,刷新数据
TI_EX SWAPF STATUS_TEMP,W
MOVWF STATUS 中断服务程序执行完毕,恢复状态寄存器原来的值
SWAPF W_TEMP,F 中断服务程序执行完毕,恢复W寄存器原来的值
SWAPF W_TEMP,W POP
BCF INTCON,T0IF 清除上次中断的标志位
BSF INTCON,T0IE 重设定时中断允许控制位
RETFIE 从中断服务子程序返回主循环程序
================================================
DISPLAY PROCESS
================================================
DISPLAY:
BSF PORTC,CS 片选控制,选中LCD模块
MOVLW 0X0C LCD ON 命令
MOVWF DIS_COMD
CALL DIS_COMMAND
MOVLW 0X80 LCD显示区第一行的地址
MOVWF DIS_COMD
CALL DIS_COMMAND
MOVLW 0X03
MOVWF SEND_DATA
MOVLW .17 连续显示“心型”
MOVWF CLEAR_X
CALL CLR_SCREEN
MOVLW 0X90 LCD显示区第二行的地址
MOVWF DIS_COMD
CALL DIS_COMMAND
MOVLW 0X03
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0X20
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XBB 第二行显示中文:欢迎进入SPI
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XB6
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XD3
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XAD
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XBD
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XF8
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XC8
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XEB
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0X53
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0X50
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0X49
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0X20
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0X20
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0X03
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0X88 LCD显示区第三行的地址
MOVWF DIS_COMD
CALL DIS_COMMAND
MOVLW 0X03
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0X20
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XCD 第三行显示中文:通信实验!
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XA8
MOVWF DIS_DATA CALL DIS_DATAS
MOVLW 0XD0
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XC5
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XCA
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XB5
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XD1
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XE9
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XA3
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0XA1
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0X20
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0X20
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0X20
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0X03
MOVWF DIS_DATA
CALL DIS_DATAS
MOVLW 0X98 LCD显示区第四行的地址
MOVWF DIS_COMD
CALL DIS_COMMAND
MOVLW 0X03
MOVWF SEND_DATA
MOVLW .17 连续显示“心型”
MOVWF CLEAR_X
CALL CLR_SCREEN
BSF PORTC,CS 片选控制,关闭LCD模块
RETURN
================================================
DIS_COMMAND
MOVLW 0XF8 SPI 的显示控制命令
CALL output
MOVF DIS_COMD,W
ANDLW 0XF0
CALL output
SWAPF DIS_COMD,W
ANDLW 0XF0
CALL output
NOP
NOP
CALL DLY_100
RETURN
DIS_DATAS SPI的数据传送命令
MOVLW 0XFA
CALL output
MOVF DIS_DATA,W
ANDLW 0XF0
CALL output
SWAPF DIS_DATA,W
ANDLW 0XF0
CALL output
NOP
NOP
CALL DLY_100
RETURN
CLR_SCREEN
DECFSZ CLEAR_X,F 传送连续字符给LCD模块
GOTO CS_1 数量由CLEAR_X决定
RETURN 内容由SEND_DATA决定
CS_1 MOVF SEND_DATA,W
MOVWF DIS_DATA
CALL DIS_DATAS
GOTO CLR_SCREEN
===========================================
output 输出到SPI缓冲区
MOVWF SSPBUF
BSF STATUS,RP0
out_loop BTFSS SSPSTAT, BF 等待缓存区空(数据发送完毕)
GOTO out_loop
BCF STATUS,RP0
RETURN
===========================================
DLY_100 MOVLW .100 软件延时 100 uS
MOVWF DELAY_100
DLY_1 DECFSZ DELAY_100,1
GOTO DLY_1
RETURN
===========================================
END
例程的源代码可以在这里下载:
id=2090" target=_blank
http://www.little-tube.com/bbs/dispbbs.asp?boardid=3id=2090