程晓DSP课程设计报告

南京邮电大学

实 验 报 告

实验名称     DSP课程设计         

                                           

                                           

课程名称______  DSP课程设计         

班级学号____         _______

姓    名_______   ____________

开课时间 2011/2012 学年,   第  1  学期

实验一、EMIF接口上的I/O接口扩展

一.实验目的

了解ICETEK-VC5509-A 板在TMS320VC5509DSP 外部扩展存储空间上的扩展。

了解ICETEK-VC5509-A 板上指示灯扩展原理。

学习在C 语言中使用扩展的控制寄存器的方法。

二.实验原理

1.TMS320VC5509DSP 的EMIF 接口:

存储器扩展接口(EMIF)是DSP 扩展片外资源的主要接口,它提供了一组控制信号和地址、

数据线,可以扩展各类存储器和寄存器映射的外设。

-ICETEK-VC5509-A 评估板在EMIF 接口上除了扩展了片外SDRAM 外,还扩展了指示灯、

DIP 开关和D/A 设备。具体扩展地址如下:

400800-400802h: D/A 转换控制寄存器

400000-400000h: 板上DIP 开关控制寄存器

400001-400001h: 板上指示灯控制寄存器

-与ICETEK-VC5509-A 评估板连接的ICETEK-CTR 显示控制模块也使用扩展空间控制主要

设备:

602800-602800h: 读-键盘扫描值,写-液晶控制寄存器

600801-600801h: 液晶辅助控制寄存器

602801-600802h: 液晶显示数据寄存器

602802-602802h: 发光二极管显示阵列控制寄存器

2.指示灯扩展原理

3.实验程序流程图:

三.部分程序代码

// 定义指示灯寄存器地址和寄存器类型

#define LBDS (*((unsigned int *)0x400001))

// 子程序接口

void Delay(unsigned int nDelay);    // 延时子程序

int i;

main()

{

    unsigned int uLED[4]={1,2,4,8}; // 控制字,逐位置1: 0001B 0010B 0100B 1000B

    CLK_init();                 // 初始化DSP运行时钟

    SDRAM_init();               // 初始化EMIF接口

    while ( 1 )

    {

        for ( i=0;i<4;i++ )

        {

            LBDS=uLED[i];       // 正向顺序送控制字

            Delay(256);         // 延时

        }

        for ( i=3;i>=0;i-- )

        {

            LBDS=uLED[i];       // 反向顺序送控制字

            Delay(32);          // 延时 【延时256->32】

        }

    }

}

四.实验结果

映射在扩展存储器空间地址上的指示灯寄存器在设置时是低4位有效的,数据的最低位对应指示灯D1,次低位对应D2,...依次类推。LED指示灯由D1→D2→D3→D4→D3→D2→D1循环依次点亮。

五.实验小结

通过本次实验,我们了解到了ICETEK-VC5509-A板在TMS320VC5509DSP外部扩展存储空间上的扩展,了解了ICETEK-VC5509-A板上指示灯扩展原理。实验过程中需要注意或者说是需要重点了解的是控制字的写入,改变控制字就可以控制不同灯的闪烁,例如要使D1、

D2灯同时闪烁,控制字就可写为3,即0011B。

实验二、定时器的使用

一.实验目的

通过实验熟悉VC5509A 的定时器;

掌握VC5509A 定时器的控制方法;

掌握VC5509A 的中断结构和对中断的处理流程;

学会C 语言中断程序设计,以及运用中断程序控制程序流程。

二.实验原理

1.通用定时器介绍及其控制方法

TMS320VC5509A 内部有两个20 位通用定时器(GP):

*每个通用定时器包括:

-一个16 位的减计数的计数器TIM;

-一个16 位的定时器周期寄存器PRD;

-一个16 位的定时器控制寄存器TCR;

-一个16 位的定时器预定标寄存器PSCR;

*PSCR 寄存器说明:

PSC: 4 位的预定标值,与TIM 共同组成20 位的定时计数器.

TDDR: 预定标周期寄存器(在需要时重装入PSC 的值)

TCR 寄存器说明

2.中断程序设计:

-程序中应包含中断向量表,VC5509A 默认向量表从程序区0 地址开始存放,根据IPVD 和

IPVH 的值确定向量表的实际地址。

-注意观察程序中INTR_init()函数的定义部分,其中IPVD 和IPVH 的值都为0x0d0;同时观察配置文件ICETEK-VC5509-A.cmd 中的VECT 段描述中o=0x0d000。

-向量表中每项为8 个字,存放一个跳转指令,跳转指令中的地址为相应服务程序入口地址。

第一个向量表的首项为复位向量,即CPU 复位操作完成后自动进入执行的程序入口。

-服务程序在服务操作完成后,清除相应中断标志,返回,完成一次中断服务。

三.实验结果

LED指示灯D1在定时器的定时中断中按照设计定时闪烁。将*prd0 = 0x0ffff改为*prd0 = 0x0fff时,指示灯闪烁的频率变大。

四.实验小结

通过本次实验,我们学会了定时器的使用,并通过控制指示灯来观察中断的进行,掌握VC5509A 的中断结构和对中断的处理流程。在实验中发现改变PRD的值会使得指示灯的闪烁频率发生变化,通过学习知道中断的次数关于PRD和TDDR的公式即为

实验三、中断的使用

一.实验目的

1.通过实验熟悉VC5509A 的中断响应过程。

2.学会C 语言中断程序设计,以及运用中断程序控制程序流程。

二.实验原理

1.中断及中断处理过程:

⑴中断简介:

中断是一种由硬件或软件驱动的信号,DSP 在接到此信号时,将当前程序悬挂起来,转

去执行另外一个任务,这个任务我们称为中断服务程序(ISR)。TMS320C55x (C55x) DSP

可支持32 个ISR,可由硬件或软件触发。

所有的C55x 中断,可以分成可屏蔽中断和不可屏蔽中断两种,软件中断是不可屏蔽的。

⑵DSP 处理中断的步骤:

①接收中断请求。请求由软件或硬件发出。

②响应中断请求。对于可屏蔽中断,需要满足若干条件,才发生响应;而对于不可屏蔽中

断,则立即响应。

③准备执行中断服务程序。

-完成当前正在执行的指令;将进入流水线但还未解码的指令清除。

-自动保存若干寄存器的值到数据堆栈和系统堆栈。

-取得用户定义的中断向量表中当前中断向量,中断向量指向中断服务程序入口。

④执行中断服务程序。中断服务程序包含中断返回指令,这样返回时可以出栈以前保存的

关键寄存器数据,从而恢复中断服务程序执行前的现场。

⑶中断向量表:

中断向量表的地址可以由用户指定。

⑷外中断:

TMS320C5509 可以响应INT0-INT4 五个外中断。

2.ICETEK-CTR 板的键盘接口:

显示/控制模块ICETEK-CTR 通过接口P8 连接小键盘,接收小键盘传送的扫描码,并在每

个扫描码结束后保存,同时向DSP 的INT2 发送中断信号;当DSP 读键盘时将扫描码送到

数据总线上。小键盘上每次按下一个键将产生2 个扫描码、2 次中断。

3.程序编制:

由一个不含中断处理程序的工程通过改写加入中断处理程序部分大致需要如下操作(假设使

用INT2):

⑴编制中断服务程序:可以用C 语言程序实现,编写单独的一个函数XINT,

此函数使用interrupt 修饰,没有参数和返回值。

⑵构造中断向量表:可以用汇编语言构造,编写一个汇编语言模块程序vector.asm,在程序

头上声明段名为“.vectors”;定义外部标号_XINT,由于汇编语言要使用C 语言程序中定义的标号XINT,需要在这个标号前加底线;在中断向量表该中断对应位置(int2)写汇编语言语句跳转语句。

⑶修改连接命令文件:在MEMORY 小节中开辟单独的地址段用以存放中断向量表;在

SECTIONS 小节中指定.vectors 段到前步开设的内存段中。

⑷主程序中进行初始化设置:定位中断向量表,使能中断,清中断等。

4.实验程序流程图:

三.部分程序代码

void InitMcBSP();

void INTR_init( void );

void TIME_init(void);

int nCount;

main()

{

    nCount=0;

    CLK_init();

    SDRAM_init();

    INTR_init();

    InitCTR();

    InitMcBSP();

    CTRGR=2;    // 使能IO

    while ( 1 )

    {

    }

}

void InitMcBSP()

{

    // IOPin: McBSP1.FSX S15 

    //SPCR2.XRST_=0,PCR.XIOEN=1,PCR.FSXM=1,PCR.FSXP=0/1

    SPCR2_1&=0x0fffe;

    PCR1|=0x2800;

}

void interrupt XINT()

{

    nCount++; nCount%=2;

    if ( nCount==0 )

        PCR1^=8;

}

void INTR_init( void )

{

    IVPD=0x80;

    IVPH=0x80;

    IER0=8;

    DBIER0=8;

    IFR0=0xffff;

    asm(" BCLR INTM");

}

四.实验结果

通过实验可以发现,每次按下键盘均会发生两次中断,当按下键不放时会产生连续的中断;只有在外中断发生时,XINT 函数才会被执行。

五.实验小结

通过本次实验,我们熟悉VC5509A 的中断响应过程,并学会C 语言中断程序设计,以及运用中断程序控制程序流程。实验过程中发现,当按住任意键不放时,指示灯会不停地闪烁即发生连续的中断,而每次按下键盘时会发生两次中断。

实验四、步进电机控制

一.实验目的

通过实验学习使用 5509DSP 的扩展I/O 端口控制外围设备信息的方法,掌握使用5509DSP

通用计时器的控制原理及中断服务程序的编程方法;了解步进电机的控制方法。

二.实验原理

1.EMIF 接口:

TMS320C5509DSP 的扩展存储器接口(EMIF)用来与大多数外围设备进行连接,典型应用如

连接片外扩展存储器等。这一接口提供地址连线、数据连线和一组控制线。ICETEK-VC5509-A将这些扩展线引到了板上的扩展插座上供扩展使用。

2.步进电机是由DSP 通用I/O 管脚输出直接控制。步进电机的起动频率大于500PPS(拍每秒),空载运行频率大于900PPS。5509A 的通用I/O 口S22 控制电机的转动频率,S14 控制转动方向。

3.控制的方法是使用DSP 通用定时器设置S22 以一定的频率改变高低状态,输出方波,设置S14 为高电平则顺时针转动,低电平为逆时针转动。

三.部分程序代码

void INTR_init( void );

void TIME_init(void);

int nCount,nStep,nAddStep;

unsigned int uTimPrd0;

unsigned int pwm2[8]={ 0x86,0x87,0x83,0x8b,0x89,0x8d,0x8c,0x8e };

main()

{

    int sEnd;

    unsigned char dbScanCode,tKey;

   

    nCount=0; nStep=1;

    sEnd=1,nAddStep=1;

    uTimPrd0=0x1002;

    CLK_init();

    SDRAM_init();

    InitCTR();

    CTRLR=0x0c2;

    TIME_init();

    INTR_init();

    do

    {

        if ( nCount>16 )

        {

            nCount=0;

            dbScanCode=GetKey();    // Scan for Keyboard input

            tKey=CTRCLKEY;          // Clear Keyboard scan buffer

            if ( dbScanCode!=0 && dbScanCode!=0x0ff )

            {

                switch(dbScanCode)

                {

                    case SCANCODE_Enter:   // Exit Program

                        sEnd=0;

                        break;

                    case SCANCODE_4:       // Motor Turn Forward

                        nAddStep=1;

                        break;

                    case SCANCODE_6:       // Motor Turn Backward

                        nAddStep=-1;

                        break;

                    case SCANCODE_Minus:   // Motor Speed Down

                        uTimPrd0+=0x800;

                        if(uTimPrd0>=0x8000)

                            uTimPrd0=0x8002;

                        asm( " BSET INTM");

                        TIME_init();

                        asm(" BCLR INTM");

                        break;

                    case SCANCODE_Plus:    // Motor Speed up

                        uTimPrd0-=0x800;

                        if(uTimPrd0<=0x1000)

                            uTimPrd0=0x1002;

                        asm( " BSET INTM");

                        TIME_init();

                        asm(" BCLR INTM");

                        break;

                }

            }

        }

    }while(sEnd);

    exit(0);

}

void interrupt Timer()

{

    CTRLR=pwm[nStep];

    nStep+=nAddStep;

    if ( nStep<0 )  nStep=7;

    else if ( nStep>7 ) nStep=0;

    nCount++;

}

void INTR_init( void )

{

    IVPD=0x80;

    IVPH=0x80;

    IER0=0x10;

    DBIER0 =0x10;

    IFR0=0xffff;

    asm(" BCLR INTM");

}

void TIME_init(void)

{

    tim0  =  (unsigned int *)0x1000;

    prd0  =  (unsigned int *)0x1001;

    tcr0  =  (unsigned int *)0x1002;

    prsc0 =  (unsigned int *)0x1003;

   *tcr0 = 0x04f0;

   *tim0 = 0x0;

   *prd0 = uTimPrd0;

   *prsc0 = 2;

   *tcr0 = 0x00e0;

}

四.实验结果

可以看到显示/控制模块上的电机指针在转动,使用“4”和“6”键可控制其转动方向,用“+”和“-”键可微调速度。如果“4”是顺时针旋转,则“6”就是逆时针旋转,“+”可以增加旋转速度,“-”是减小速度,但是变化都是很微小。

五.实验小结

通过实验学习使用 5509DSP 的扩展I/O 端口控制外围设备信息的方法,掌握使用5509DSP通用计时器的控制原理及中断服务程序的编程方法;了解步进电机的控制方法。

实验五、多路信号混频

一.实验目的

掌握A/D 转换的基本过程和程序处理过程;

学习通过对采样值进行计算产生混频波形。

二.实验原理

1.模数转换工作过程:

-模数转换模块接到启动转换信号后,按照设置进行相应通道的数据采样转换。

-经过一个采样时间的延迟后,将采样结果放入AD 数据寄存器中保存。

-等待下一个启动信号。

2.模数转换的程序控制:

模数转换相对于计算机来说是一个较为缓慢的过程。一般采用中断方式启动转换或保存结

果,这样在CPU 忙于其他工作时可以少占用处理时间。设计转换程序应首先考虑处理过程如何与模数转换的时间相匹配,根据实际需要选择适当的触发转换的手段,也要能及时地保存结果。由于TMS320VC5509DSP 片内的A/D 转换精度是10 位的,转换结果(16 位)的最高位(第15位)表示转换值是否有效(0 有效),第14-12 位表示转换的通道号,低10 位为转换数值,所以在保留时应注意取出结果的低10 位,再根据高4 位进行相应保存。

4.混频波形产生:

将接收到的两路AD 采集信号进行相加,并对结果的幅度进行限制,从而产生混合后的输出

波形。实验中采用了同相位混频方法,也可修改程序完成异相混频法。

5.源程序及注释:

本实验程序在主循环中对AD 进行连续采样,每次采样首先设置AD 转换控制寄存器(ADCCTL),发送转换通道号和启动命令,然后循环等待转换结果,最后将结果保存。由于需要进行实时混频,所以交替转换通道0 和通道1(ICETEK-VC5509-EDU 实验箱上ADCIN2 和ADCIN3)。

三.部分程序代码

void InitADC();

void wait( unsigned int cycles );

void EnableAPLL( );

unsigned int nADC0[256],nADC1[256],nMixing[256];

main()

{

    int i;

    unsigned int uWork;

    EnableAPLL();

    SDRAM_init();

    InitCTR();

    InitADC();

    PLL_Init(144);

    while ( 1 )

    {

        for ( i=0;i<256;i++ )

        {

            ADCCTL=0x8000;  // 启动AD转换,通道0

            do

            {

                uWork=ADCDATA;

            } while ( uWork&0x8000 );

            nADC0[i]=uWork&0x0fff;

            ADCCTL=0x9000;  // 启动AD转换,通道1

            do

            {

                uWork=ADCDATA;

            } while ( uWork&0x8000 );

            nADC1[i]=uWork&0x0fff;

            uWork=(nADC0[i]+nADC1[i]);  // 混频

            uWork>>=1;                  // 限幅,混频后仍然产生12位数据

//          uWork=(nADC0[i]+nADC1[i]*3);

//          uWork>>=2;

            nMixing[i]=uWork;

        }

    }                           // 在此加软件断点

}

void InitADC()

{

    ADCCLKCTL=0x23; // 4MHz ADCLK

    ADCCLKDIV=0x4f00;

}

void wait( unsigned int cycles )

{

    int i;

    for ( i = 0 ; i < cycles ; i++ ){ }

}

四.实验结果

五.实验体会

掌握A/D 转换的基本过程和程序处理过程;

学习通过对采样值进行计算产生混频波形。

实验六、异步串口通信

. 实验目的

了解ICETEK-VC5509-A 评估板上扩展标准RS-232 串行通信接口的原理和方法。

学会对串行通信芯片的配置编程。

学习设计异步通信程序。

二.实验原理

1.ICETEK-VC5509-A 板异步串口设计。

在板上加上16C550、Max232 和驱动电路部分即可。驱动电路主要完成将输出的0-3.3V 电

平转换成异步串口的工作电平,转换电平的工作由MAX232 芯片完成,但由于它是5V 器件所以它同DSP 间的信号线必须有电平转换,此板采用的是74LVC245。

2.串行通信接口设置。

内部生成的串行时钟由系统时钟SYSCLK 频率和波特率选择寄存器决定。串行通信接口使

用16 位波特率选择寄存器,数据传输的速度可以被编程为65000 多种不同的方式。

不同通信模式下的串行通信接口异步波特率由下列方法决定:

-BRR=1—65535 时的串行通信接口异步波特率:

串行通信接口异步波特率=SYSCLK/[( BRR+1)*8]。其中,BRR=SYSCLK/(SCI 异步波特率*8)-1;

-BRR=0 时的串行通信接口异步波特率:

串行通信接口异步波特率=SYSCLK/16。这里BRR 等于波特率选择寄存器的16 位值。

3.实验程序流程图:

. 实验结果

通过 DSP 传送到PC 机上的信息,可以看出:串口正确工作。我们在“发送的字符/数据”栏中输入一些要发送到DSP 的字符串,例如“Hello,man!”,以“.”字符结尾,然后单击“手动发送”按钮后,在“串口调试助手”的接收窗口中可看到“oh,you say Hello,man!”的回答。

五. 实验体会

通过本次实验,我们了解了ICETEK-VC5509-A 评估板上扩展标准RS-232 串行通信接口的原理和方法。学会对串行通信芯片的配置编程。学习设计异步通信程序。

 综合设计2LCD液晶显示

一.实验原理

1.EMIF 接口:

TMS320C5509DSP 的扩展存储器接口(EMIF)用来与大多数外围设备进行连接,典型应用如

连接片外扩展存储器等。这一接口提供地址连线、数据连线和一组控制线。ICETEK-VC5509-A将这些扩展线引到了板上的扩展插座上供扩展使用。

2.液晶显示模块的访问、控制是由5509ADSP 对扩展接口的操作完成。

控制口的寻址:命令控制接口的地址为0x602800,数据控制接口的地址为0x602801 和

0x600802,辅助控制接口的地址为0x600801。

3.显示控制方法:

液晶显示模块中有两片显示缓冲存储器,分别对应屏幕显示的象素,向其中写入数值将改变

显示,写入“1”则显示一点,写入“0”则不显示。其地址与象素的对应方式如下:

-发送控制命令:向液晶显示模块发送控制命令的方法是通过向命令控制接口写入命令控制字,然后再向辅助控制接口写入0。下面给出的是基本命令字、解释和C 语言控制语句

举例:

.显示开关:0x3f 打开显示;0x3e 关闭显示;

.设置显示起始行:0x0c0+起始行取值,其中起始行取值为0 至63;

.设置操作页:0x0b8+页号,其中页号取值为0-7;

.设置操作列:0x40+列号,其中列号为取值为0-63;

-写显示数据:在使用命令控制字选择操作位置(页数、列数)之后,可以将待显示的数据写

入液晶显示模块的缓存。将数据发送到相应数据控制I/O 接口即可。

4.液晶显示器与DSP 的连接:

5.数据信号的传送:

由于液晶显示模块相对运行在高主频下的DSP属于较为慢速设备,连接时需要考虑数据线上信号的等待问题;

电平转换:由于DSP 为3.3V 设备,而液晶显示模块属于5V 设备,所以在连接控制线、数据线时需要加电平隔离和转换设备,如:ICETEK-CTR 板上使用了74LS245。

6.实验程序流程图:

.实验要求概述

本实验通过对液晶显示屏的显示行、列、页的设置,并编写相关的序号和姓名代码,运用液晶显示模块的命令控制接口、数据控制接口以及辅助控制接口等地址,和左屏、右屏运用的不同方法实现在液晶显示屏上显示我们的学号及姓名。

三. 关键部分程序代码

1.控制显示内容:#include "scancode.h"

// Variables  程晓涛 

unsigned char lcdbuf[9]={'B','0','8','0','2','1','5','2','8'};

unsigned char Line1[]=

{0x04,0x03,0x00,0xFF,0x00,0x41,0x44,0x44,0x44,0x7F,0x44,0x44,0x44,0x44,0x40,0x00,

0x00,0x0F,0x04,0x04,0x4F,0x21,0x19,0x07,0x01,0x01,0x3F,0x41,0x40,0x41,0x71,0x00,

0x04,0xFC,0x03,0x20,0x18,0x06,0x01,0x02,0x0A,0x52,0x82,0x7F,0x02,0x02,0x02,0x00};

unsigned char Line2[]=

{0x10,0x12,0xD2,0xFE,0x91,0x11,0x80,0xBF,0xA1,0xA1,0xA1,0xA1,0xBF,0x80,0x00,0x00,

0x00,0xFE,0x42,0x42,0xFE,0x00,0x84,0x84,0x47,0x5C,0x24,0x64,0x94,0x04,0xC0,0x00,

0x10,0x61,0x86,0x70,0x40,0x54,0xD4,0x74,0x5F,0x54,0x54,0xD4,0x54,0x54,0x40,0x00};

unsigned char ledbuf[8],ledx[8];

/*****通信*****/

unsigned char Line3[]=

{0x40,0x20,0x1F,0x20,0x40,0x5F,0x42,0x42,0x42,0x5F,0x4A,0x52,0x4F,0x40,0x40,0x00,

0x00,0x00,0x00,0x7F,0x00,0x00,0x7E,0x22,0x22,0x22,0x22,0x22,0x7E,0x00,0x00,0x00};

unsigned char Line4[]=

{0x40,0x41,0xC6,0x00,0x00,0xF2,0x52,0x52,0x56,0xFA,0x5A,0x56,0xF2,0x00,0x00,0x00,

0x80,0x40,0x30,0xFC,0x07,0x0A,0xA8,0xA8,0xA9,0xAE,0xAA,0xA8,0xA8,0x08,0x08,0x00};

/*****通信*****/

/********工程******/

unsigned char Line5[]=

{0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,

0x04,0x03,0x00,0xFF,0x00,0x41,0x44,0x44,0x44,0x7F,0x44,0x44,0x44,0x44,0x40,0x00};

unsigned char Line6[]=

{0x00,0x00,0x02,0x02,0x02,0x02,0x02,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,

0x10,0x12,0xD2,0xFE,0x91,0x11,0x80,0xBF,0xA1,0xA1,0xA1,0xA1,0xBF,0x80,0x00,0x00};

/********工程******/

2.控制显示位置:LCD.C

CTRLCDCMDR=LCDCMDSTARTLINE;     // 换行

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

   

        CTRLCDCMDR=LCDCMDPAGE+1;        // 设置操作页=0

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        CTRLCDCMDR=LCDCMDVERADDRESS;    // 起始列=0

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        for ( i=0;i<48;i++ )

        {

            nCount=Line1[i];

            CTRLCDRCR=( nBW==0 )?(nCount):(~nCount);    // 屏幕左侧第1至8行第i列赋值                          port8002=0;           // (赋值后当前操作列自动加1,所以不需设置)

            Delay(LCDDELAY);

            CTRLCDCR=0;

            Delay(LCDDELAY);

        }

详细代码请查看附录。

四. 实验结果

液晶显示屏显示出自己的学号和姓名及专业,即:

B08021528 程晓涛

通信        工程

学号的每个字符之间是以一定的延时显现出来,最后稳定。通过字模软件中设置不同的字体可以得出不同的中文字编码。

五.实验小结

这次试验用显示屏是64X128的,我们设置的数字式8个字节,共九个数字,所以在左屏输出8个右屏输出一个,汉字设置的是16x16全部在右屏输出。汉字要经过字母软件处理后才可用,汉字分上下两页和左右两页,可以通过改变页码来改变汉字位置。

通过此次实验,让我对单片机的知识有了进一步的了解,由于以前曾参加过MSP430单片机项目,所以做起来稍微容易些。下面我概括了几点我的学习经验和心得体会:

1、万事开头难、要勇敢迈出第一步。开始的时候,不要老是给自己找借口,说考研没时间啦、没有实验板啦之类的。遇到困难要一件件攻克,不会建项目,就先学它,这方面教程很多,随便找找看一下,做几次就懂了。然后可以参考别的人程序,抄过来也无所谓,写一个最简单的,让它运行起来,先培养一下自己的感觉,知道写程序是怎么一回事,无论写大程序还是小程序,要做的工序不会差多少。写好程序在上面运行一下看结果,学习效果会好很多,仿真器就看个人需要了。单片机是注重理论和实践的,光看书不动手,是学不会的。

2、 知识点用到才学,不用的暂时丢一边。厚厚的一本书,看着人头都晕了,学了后面的,前面的估计也快忘光了,所以,最好结合实际程序,用到的时候才去看,不必 说非要把书从第一页看起,看完它才来写程序。比如你写流水灯,完全就没必要看中断的知识,专心把流水灯学好就是了,这是把整本书化整为零,一小点一小点的啃。

3、程序不要光看不写,一定要自己写一次。最开始的时候,啥都不懂,可以抄人家的程序过来,看看每一句是干什么用的,达到什么目的,运 行后有什么后果,看明白了之后,就要自己写一次,你会发现,原来看明白别人的程序很容易,但到自己写的时候却一句也写不出来,这就是差距。。。当你自己能 写出来的时候,说明你就真的懂了。。。

4、必须学会掌握调试程序的方法。不少人写程序,把代码写好了,然后一运行,不是自己想要的结果,就晕了。这就需要学习调试程序的方法,比如KEIL里,可以下断点啦,查看寄存器内容等等,这些都是调试程序的手段,当你发现你写的程序运行结 果和你想象中不一样的时候,你可以单步,也可以下断点,然后跟踪,查看各相关寄存器内容,看看程序运行过中是不是有什么偏差,找出影响结果的地方,改正过来。这一个过程非常重要,通过程序的排错,你可以学到的知识是书上得不到的。

5、开动脑筋,运用多种方法,不断优化 自己的程序。想想用各种不同方法来实现同一功能。这是一个练习和提高的过程,一个问题,你解决了,那么你再想想,能不能换种写法,也可以实现同一功能,或 者说,你写出来的代码,能不能再精简一点,让程序执行效率更高,这个过程,就是一个进步的过程。很多知识和经验的获得,并不是直接写在书让你看就可以得到 的,需要自己去实践,开动脑筋,经验才能得到积累,编程水平才能有所提高。

6、看别人的代码,学习人家的思路。这个在学习初期是很有用,通过看别人的代码,特别是有多年编程经验的人写出的具有一定水平的代码,可以使自己编程水平得到迅速的提高,同时,也可以结合别人的编程手法,与自己的想法 融合在一起,写出更高水平的代码,从中得到进步。但要注意,切忌将学习变成抄袭,更不是抄袭完了就认为自己学会了,这样做只会使你退步。

7、 尝试编写一下综合应用的程序。从流水灯学起,到动态扫描,再到中断,那么,你可以试试写一下时钟这种综合性应用的程序,不要小看时钟,要写好它不是一件容 易的事情,它包括了单片机大部分的知识,比如有按键(IO读取)、动态扫描(IO输出)、中断等,如何协调好各功能模块正常工作,才是编程者需要学习的地 方,当你单独写一个功能的时候,比如按键读取,你可能感觉很容易,因为你的程序啥也不做,只是读按键。但把它和其它功能混合在一起,如何在整个程序运行中 使每一部分都正常工作,这就不是写一个按键读取这么容易的事情,功能模块之间有可能会互相影响,比如你需要让数码管既能显示,又要去处理按键读取,怎么使 这两部分都正常工作,这就是一个协调过程。当你有了这个处理协调能力,你就算是入门了。

8、着重于培养解决问题的能力,而不是具体看自己编 写了多少代码或者做过什么。“学单片机重点在于学习解决问题的思路,而不是局限于具体的芯片类型和语言”这一直是我的座右铭,是我学单片机多年来感悟出来 的。经常看到有人说“你会驱动XX芯片,真牛啊”“你搞过XX项目,真厉害”之类的话,其实这是非常片面的,搞过XX芯片,搞过XX项目,只能说明你做过 这一项目,它只是你的业绩,并不是代表能力就一定高。真正的能力应该是:“遇到没有解决过的问题或器件,能利用自己已学的知识,迅速找到解决问题的方 法。”这个才是能力。写程序的过程就是一个创造的过程,几乎没有完全一样的项目,每次你遇上的几乎都不相同,所以你拥有的必须是你面对新项目时的创造能 力,而不是标榜着你以往做过多少项目。当然,业绩也能从另一侧面反映你的经验和水平。

9、面对一个新项目时,多自己开动脑筋,不要急于找别人的程序。有不少人面对一个新项目时,第一步想到的就是网上找别人写过 的代码,然后抄一段,自己再写几句,凑在一起就完成任务,这虽然可能是省时间,但绝对不利你的学习。当你接到一个新项目时,应该先自己构思一下整个程序的 架构,想想如何来完成,有可能的话,画一个流程图,简单的可以画在脑子里,对程序中用到的数据、变量有一个初步的安排,然后自己动手去写,遇到实在没办法 解决的地方,再去请教别人,或看别人是怎么处理的,这样首先起码你自己动过脑想过,自己有自己的思路,如果你一开始就看别人的程序,你的思维就会受限在别 人的思维里,自己想再创新就更难了,这样你自己永远也没办法提高,因为你是走在别人的影子里。

10、多利用网络的搜索,学会提问题。一般来 说,学习过程中,你遇上的问题,前人们多数也有遇上的,所以如果有什么不懂,在自己解决不了的时候,最好先到网上搜索一下,看能不能找到答案,找不到再到 论坛里发问,发问也要有目的性,尽量简单明了的描述问题,让帮助你的人可以用最少的时间就看懂你说什么,毕竟人家帮助你是免费的,时间也是有限的。

总之,通过本次试验。感觉自己知识有了不少提升,尤其在硬件方面获益匪浅。

附录:程序详细代码

1.  控制显示内容:#include "scancode.h"

   #include "scancode.h"

// McBSP0  ------------------------------------------------------

#define SPCR0 (*(unsigned int *)0x018c0008)

#define PCR0 (*(unsigned int *)0x018c0024)

#define SPCR01 (*(unsigned int *)0x01900008)

#define SPCR02 (*(unsigned int *)0x0)

// McBSP1  ------------------------------------------------------

ioport unsigned int *SPCR21=(unsigned int *)0x2c04;

ioport unsigned int *PCR_1=(unsigned int *)0x2c12;

#define SPCR2_1 (*SPCR21)

#define PCR1 (*PCR_1)

// McBSP2  ------------------------------------------------------

ioport unsigned int *SPCR12=(unsigned int *)0x3005;

ioport unsigned int *PCR_2=(unsigned int *)0x3012;

#define SPCR1_2 (*SPCR12)

#define PCR2 (*PCR_1)

// ICETEK-VC5509-A -----------------------------------------------

#define LBDS (*((unsigned int *)0x40001))

#define DIPS (*(unsigned int *)0x400002)

// ICETEK-CTR  --------------------------------------------------

#define CTRGR (*(unsigned int *)0x600800)

#define CTRKEY (*(unsigned int *)0x602800)

#define CTRCLKEY (*(unsigned int *)0x602801)

#define CTRLA (*(unsigned int *)0x602802)

#define CTRLR (*(unsigned int *)0x602803)

#define CTRLCDCMDR (*(unsigned int *)0x602800)

#define CTRLCDCR (*(unsigned int *)0x600801)

#define CTRLCDLCR (*(unsigned int *)0x602801)

#define CTRLCDRCR (*(unsigned int *)0x600802)

// Special values -----------------------------------------------

#define LCDCMDTURNON 0x3f

#define LCDCMDTURNOFF 0x3e

#define LCDCMDSTARTLINE 0xc0

#define LCDCMDPAGE 0xb8

#define LCDCMDVERADDRESS 0x40

// Variables  程晓涛 

unsigned char lcdbuf[9]={'B','0','8','0','2','1','5','2','8'};

unsigned char Line1[]=

{0x04,0x03,0x00,0xFF,0x00,0x41,0x44,0x44,0x44,0x7F,0x44,0x44,0x44,0x44,0x40,0x00,

0x00,0x0F,0x04,0x04,0x4F,0x21,0x19,0x07,0x01,0x01,0x3F,0x41,0x40,0x41,0x71,0x00,

0x04,0xFC,0x03,0x20,0x18,0x06,0x01,0x02,0x0A,0x52,0x82,0x7F,0x02,0x02,0x02,0x00};

unsigned char Line2[]=

{0x10,0x12,0xD2,0xFE,0x91,0x11,0x80,0xBF,0xA1,0xA1,0xA1,0xA1,0xBF,0x80,0x00,0x00,

0x00,0xFE,0x42,0x42,0xFE,0x00,0x84,0x84,0x47,0x5C,0x24,0x64,0x94,0x04,0xC0,0x00,

0x10,0x61,0x86,0x70,0x40,0x54,0xD4,0x74,0x5F,0x54,0x54,0xD4,0x54,0x54,0x40,0x00};

unsigned char ledbuf[8],ledx[8];

/*****通信*****/

unsigned char Line3[]=

{0x40,0x20,0x1F,0x20,0x40,0x5F,0x42,0x42,0x42,0x5F,0x4A,0x52,0x4F,0x40,0x40,0x00,

0x00,0x00,0x00,0x7F,0x00,0x00,0x7E,0x22,0x22,0x22,0x22,0x22,0x7E,0x00,0x00,0x00};

unsigned char Line4[]=

{0x40,0x41,0xC6,0x00,0x00,0xF2,0x52,0x52,0x56,0xFA,0x5A,0x56,0xF2,0x00,0x00,0x00,

0x80,0x40,0x30,0xFC,0x07,0x0A,0xA8,0xA8,0xA9,0xAE,0xAA,0xA8,0xA8,0x08,0x08,0x00};

/*****通信*****/

/********工程******/

unsigned char Line5[]=

{0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,

0x04,0x03,0x00,0xFF,0x00,0x41,0x44,0x44,0x44,0x7F,0x44,0x44,0x44,0x44,0x40,0x00};

unsigned char Line6[]=

{0x00,0x00,0x02,0x02,0x02,0x02,0x02,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,

0x10,0x12,0xD2,0xFE,0x91,0x11,0x80,0xBF,0xA1,0xA1,0xA1,0xA1,0xBF,0x80,0x00,0x00};

/********工程******/

unsigned char ledkey[10][8]=

{

    {0x00,0x00,0x7C,0x82,0x82,0x82,0x7C,0x00},  //0

    {0x00,0x00,0x00,0x84,0xFE,0x80,0x00,0x00},  //1

    {0x00,0x00,0x84,0xC2,0xA2,0x92,0x8C,0x00},  //2

    {0x00,0x00,0x44,0x92,0x92,0x92,0x6C,0x00},

    {0x00,0x00,0x30,0x28,0x24,0xFE,0x20,0x00},

    {0x00,0x00,0x4E,0x92,0x92,0x92,0x62,0x00},

    {0x00,0x00,0x7C,0x92,0x92,0x92,0x64,0x00},

    {0x00,0x00,0x02,0xC2,0x32,0x0A,0x06,0x00},

    {0x00,0x00,0x6C,0x92,0x92,0x92,0x6C,0x00},

    {0x00,0x00,0x4C,0x92,0x92,0x92,0x7C,0x00}

};

unsigned char PIXEL_ENGLISH_CHAR[ ][ 5 ] =

{

    { 0x3E, 0x51, 0x49, 0x45, 0x3E },   // 0

    { 0x00, 0x42, 0x7F, 0x40, 0x00 },   // 1

    { 0x42, 0x61, 0x51, 0x49, 0x46 },   // 2

    { 0x21, 0x41, 0x45, 0x4B, 0x31 },   // 3

    { 0x18, 0x14, 0x12, 0x7F, 0x10 },   // 4

    { 0x27, 0x45, 0x45, 0x45, 0x39 },   // 5

    { 0x3C, 0x4A, 0x49, 0x49, 0x30 },   // 6

    { 0x01, 0x71, 0x09, 0x05, 0x03 },   // 7

    { 0x36, 0x49, 0x49, 0x49, 0x36 },   // 8

    { 0x06, 0x49, 0x49, 0x29, 0x1E },   // 9

    { 0x7E, 0x11, 0x11, 0x11, 0x7E },   // A

    { 0x7F, 0x49, 0x49, 0x49, 0x36 },   // B

    { 0x3E, 0x41, 0x41, 0x41, 0x22 },   // C

    { 0x7F, 0x41, 0x41, 0x22, 0x1C },   // D

    { 0x7F, 0x49, 0x49, 0x49, 0x41 },   // E

    { 0x7F, 0x09, 0x09, 0x09, 0x01 },   // F

    { 0x3E, 0x41, 0x49, 0x49, 0x7A },   // G

    { 0x7F, 0x08, 0x08, 0x08, 0x7F },   // H

    { 0x00, 0x41, 0x7F, 0x41, 0x00 },   // I

    { 0x20, 0x40, 0x41, 0x3F, 0x01 },   // J

    { 0x7F, 0x08, 0x14, 0x22, 0x41 },   // K

    { 0x7F, 0x40, 0x40, 0x40, 0x40 },   // L

    { 0x7F, 0x02, 0x0C, 0x02, 0x7F },   // M

    { 0x7F, 0x04, 0x08, 0x10, 0x7F },   // N

    { 0x3E, 0x41, 0x41, 0x41, 0x3E },   // O

    { 0x7F, 0x09, 0x09, 0x09, 0x06 },   // P

    { 0x3E, 0x41, 0x51, 0x21, 0x5E },   // Q

    { 0x7F, 0x09, 0x19, 0x29, 0x46 },   // R

    { 0x46, 0x49, 0x49, 0x49, 0x31 },   // S

    { 0x01, 0x01, 0x7F, 0x01, 0x01 },   // T

    { 0x3F, 0x40, 0x40, 0x40, 0x3F },   // U

    { 0x1F, 0x20, 0x40, 0x20, 0x1F },   // V

    { 0x3F, 0x40, 0x38, 0x40, 0x3F },   // W

    { 0x63, 0x14, 0x08, 0x14, 0x63 },   // X

    { 0x07, 0x08, 0x70, 0x08, 0x07 },   // Y

    { 0x61, 0x51, 0x49, 0x45, 0x43 },   // Z

  

};

unsigned char lcd_b[]={0x00,0x00,0x7F, 0x49, 0x49, 0x49, 0x36,0x00};   // B

#define nMusicNumber 52

unsigned int music[nMusicNumber][2]=

{

    {101,1920},{121,1440},{114,480},{101,1920},{151,1920},

    {151,480},{135,480},{121,480},{101,480},{114,960},{121,960},{135,3840},

    {121,480},{114,480},{101,480},{91,480},{101,960},{101,960},

    {76,1920},{101,1920},{114,960},{121,960},{135,1440},{151,480},{151,1920},{0,1920},

    {101,1920},{121,1440},{114,480},{101,1920},{151,1920},

    {151,480},{135,480},{121,480},{101,480},{114,960},{121,960},{135,3840},

    {121,480},{114,480},{101,480},{91,480},{101,960},{101,960},

    {76,1920},{101,1920},{114,960},{121,960},{135,1440},{151,480},{151,1920},{0,1920}

};

unsigned int pwm[8]={ 0x86,0x87,0x83,0x8b,0x89,0x8d,0x8c,0x8e };

unsigned char dbClearKey;

主函数:

// Functions

void InitInterrupt(void);           // 初始化中断

void InitCTR();                     // 初始化ICETEK-CTR

void CloseCTR();                    // 关闭ICETEK-CTR上各设备

void Delay(unsigned int nTime);     // 延时子程序

void Delay1(unsigned int nTime);    // 延时子程序(带LED显示刷新)

unsigned char GetKey();             // 读取键盘输入

void RefreshLEDArray();             // 刷新发光二极管阵列显示

void SetLEDArray(int nNumber);      // 修改发光二极管阵列显示内容

char ConvertScanToChar(unsigned char cScanCode);    // 将键盘扫描码转换成字符

void LCDCMD(unsigned char dbCommand);   // 向液晶显示器发送命令

void LCDWriteLeft(unsigned char dbData);    // 写液晶显示器左半屏

void LCDCLS();                          // 清除液晶显示器显示

void TurnOnLCD();                       // 打开液晶显示器

void CloseCTR()

{

    CTRGR=0;                 

    CTRLR=0; CTRLR=0x40;

    CTRLR=0x0c0;

    LCDCMD(LCDCMDTURNOFF); 

    dbClearKey=CTRCLKEY;

    LBDS=0;

}

void LCDCMD(unsigned char dbCommand)

{

    CTRLCDCMDR=dbCommand;      

    CTRLCDCR=0;

}

unsigned char GetKey()

{

    unsigned char dbReturn;

   

    dbReturn=CTRKEY;

    dbClearKey=CTRCLKEY;

    return dbReturn;

}

char ConvertScanToChar(unsigned char cScanCode)

{

    char cReturn;

   

    cReturn=0;

    switch ( cScanCode )

    {

        case SCANCODE_0: cReturn='0'; break;

        case SCANCODE_1: cReturn='1'; break;

        case SCANCODE_2: cReturn='2'; break;

        case SCANCODE_3: cReturn='3'; break;

        case SCANCODE_4: cReturn='4'; break;

        case SCANCODE_5: cReturn='5'; break;

        case SCANCODE_6: cReturn='6'; break;

        case SCANCODE_7: cReturn='7'; break;

        case SCANCODE_8: cReturn='8'; break;

        case SCANCODE_9: cReturn='9'; break;

        case SCANCODE_Plus: cReturn='+'; break;

        case SCANCODE_Minus: cReturn='-'; break;

    }

    return cReturn;

}

void InitCTR()

{

    int i;

   

    for ( i=0;i<8;i++ )

    {

        ledbuf[i]=0x0ff;        // 显示为空白

        ledx[i]=(i<<4); // 生成显示列控制字

    }

    CTRGR=0; CTRGR=0x80; CTRGR=0;

    CTRLR=0; CTRLR=0x40;

    CTRLR=0x0c0;

    LCDCMD(LCDCMDTURNOFF); 

    dbClearKey=CTRCLKEY;

    LBDS=0;

}

void Delay(unsigned int nDelay)

{

    int ii,jj,kk=0;

    for ( ii=0;ii<nDelay;ii++ )

    {

        for ( jj=0;jj<1024;jj++ )

        {

            kk++;

        }

    }

}

void Delay1(unsigned int nDelay)

{

    int ii,jj,kk=0;

    for ( ii=0;ii<nDelay;ii++ )

    {

        for ( jj=0;jj<64;jj++ )

        {

            RefreshLEDArray();

            kk++;

        }

    }

}

void RefreshLEDArray()

{

    int i;

    for ( i=0;i<8;i++ )

    {

        CTRGR=ledx[i];

        CTRLA=ledbuf[i];

    }

}

void SetLEDArray(int nNumber)

{

    int i;

    for ( i=0;i<8;i++ )

        ledbuf[i]=~ledkey[nNumber][7-i];

}

void LCDWriteLeft(unsigned char dbData)

{

    CTRLCDLCR=dbData;

    CTRLCDCR=0;

}

void LCDWriteRight(unsigned char dbData)

{

    CTRLCDRCR=dbData;

    CTRLCDCR=0;

}

void TurnOnLCD()

{

    LCDCMD(LCDCMDTURNON);

}

void LCDCLS()

{

    int i,j;

    LCDCMD(LCDCMDSTARTLINE);

    for ( i=0;i<8;i++ )

    {

        LCDCMD(LCDCMDPAGE+i);

        LCDCMD(LCDCMDVERADDRESS);

        for ( j=0;j<64;j++ )

            LCDWriteLeft(0);

        LCDCMD(LCDCMDPAGE+i);

        LCDCMD(LCDCMDVERADDRESS);

        for ( j=0;j<64;j++ )

            LCDWriteRight(0);

    }

}

             

在写下一行学号和姓名时,需要将学号和姓名的操作页分别设置成下一页,这样才能写出两行的姓名和学号。

2.控制显示位置:lcd.c

#define LCDDELAY 1

#include "myapp.h"

#include "ICETEK-VC5509-EDU.h"

#include "scancode.h"

main()

{

    int i,j,nCount=0,nBW=0;

    CLK_init();

    SDRAM_init();

    InitCTR();

    TurnOnLCD();                // 打开显示

    LCDCLS();               // 清除显示内存

    CTRLCDCMDR=LCDCMDSTARTLINE;     // 设置显示起始行

    Delay(LCDDELAY);

    CTRLCDCR=0;

    Delay(LCDDELAY);

   

        CTRLCDCMDR=LCDCMDPAGE;      // 设置操作页=0

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        CTRLCDCMDR=LCDCMDVERADDRESS+15; // 起始列=0

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        for ( j=0;j<9;j++)

        {

            for ( i=0;i<5;i++ )

            {

                nCount=lcdbuf[j]-32;

                CTRLCDLCR=( nBW==0 )?(PIXEL_ENGLISH_CHAR[nCount][i]):(~PIXEL_ENGLISH_CHAR[nCount][i]);   // 屏幕左侧第1至8行第i列赋值                          port8002=0;           // (赋值后当前操作列自动加1,所以不需设置)

                Delay(LCDDELAY);

                CTRLCDCR=0;

                Delay(LCDDELAY);

            }

        }

        Delay(512);

        nCount++;

        if ( nCount==10 )

        {

            nCount=0;

            nBW=1-nBW;

        }

       

/********************************************/     

       

        CTRLCDCMDR=LCDCMDSTARTLINE;     // 换行

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

   

        CTRLCDCMDR=LCDCMDPAGE+1;        // 设置操作页=0

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        CTRLCDCMDR=LCDCMDVERADDRESS;    // 起始列=0

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        for ( i=0;i<48;i++ )

        {

            nCount=Line1[i];

            CTRLCDRCR=( nBW==0 )?(nCount):(~nCount);    // 屏幕左侧第1至8行第i列赋值                          port8002=0;           // (赋值后当前操作列自动加1,所以不需设置)

            Delay(LCDDELAY);

            CTRLCDCR=0;

            Delay(LCDDELAY);

        }

/**********************************************/

        CTRLCDCMDR=LCDCMDSTARTLINE;     // 换行

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

   

        CTRLCDCMDR=LCDCMDPAGE;      // 设置操作页=0 !!!关键地方

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        CTRLCDCMDR=LCDCMDVERADDRESS;    // 起始列=0

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        for ( i=0;i<48;i++ )

        {

            nCount=Line2[i];

            CTRLCDRCR=( nBW==0 )?(nCount):(~nCount);    // 屏幕左侧第1至8行第i列赋值                          port8002=0;           // (赋值后当前操作列自动加1,所以不需设置)

            Delay(LCDDELAY);

            CTRLCDCR=0;

            Delay(LCDDELAY);

        }

/***************************************************/

        CTRLCDCMDR=LCDCMDPAGE+3;        // 设置操作页=0 !!!关键地方

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        CTRLCDCMDR=LCDCMDVERADDRESS+35; // 起始列=0

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        for ( i=0;i<32;i++ )

        {

            nCount=Line3[i];

            CTRLCDLCR=( nBW==0 )?(nCount):(~nCount);    // 屏幕左侧第1至8行第i列赋值                          port8002=0;           // (赋值后当前操作列自动加1,所以不需设置)

            Delay(LCDDELAY);

            CTRLCDCR=0;

            Delay(LCDDELAY);

        }

/***************************************************/

        CTRLCDCMDR=LCDCMDPAGE+2;        // 设置操作页=0 !!!关键地方

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        CTRLCDCMDR=LCDCMDVERADDRESS+35; // 起始列=0

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        for ( i=0;i<32;i++ )

        {

            nCount=Line4[i];

            CTRLCDLCR=( nBW==0 )?(nCount):(~nCount);    // 屏幕左侧第1至8行第i列赋值                          port8002=0;           // (赋值后当前操作列自动加1,所以不需设置)

            Delay(LCDDELAY);

            CTRLCDCR=0;

            Delay(LCDDELAY);

        }

/***************************************************/

/***************************************************/

        CTRLCDCMDR=LCDCMDPAGE+3;        // 设置操作页=0 !!!关键地方

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        CTRLCDCMDR=LCDCMDVERADDRESS;    // 起始列=0

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        for ( i=0;i<32;i++ )

        {

            nCount=Line5[i];

            CTRLCDRCR=( nBW==0 )?(nCount):(~nCount);    // 屏幕左侧第1至8行第i列赋值                          port8002=0;           // (赋值后当前操作列自动加1,所以不需设置)

            Delay(LCDDELAY);

            CTRLCDCR=0;

            Delay(LCDDELAY);

        }

/***************************************************/

        CTRLCDCMDR=LCDCMDPAGE+2;        // 设置操作页=0 !!!关键地方

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        CTRLCDCMDR=LCDCMDVERADDRESS;    // 起始列=0

        Delay(LCDDELAY);

        CTRLCDCR=0;

        Delay(LCDDELAY);

        for ( i=0;i<32;i++ )

        {

            nCount=Line6[i];

            CTRLCDRCR=( nBW==0 )?(nCount):(~nCount);    // 屏幕左侧第1至8行第i列赋值                          port8002=0;           // (赋值后当前操作列自动加1,所以不需设置)

            Delay(LCDDELAY);

            CTRLCDCR=0;

            Delay(LCDDELAY);

        }

/***************************************************/

    for (;;)

    {

    }

}              

相关推荐