atmega8 例程:12864例程

 
/*****************************************************************
*  函数库说明:ATMEGA8 NOKIA 12864LCD 驱动
*  版本:      v1.02									       
*  修改:      庞辉    芜湖联大飞思卡尔工作室             									       
*  修改日期:  2011年08月08日 							   
*			   											   
*  说明:	   ST7920(带字库)
*              AVR只可以运行在4Mhz晶振下,8Mhz就已经无法显示
               atmega8的PB6和PB7为晶振引脚,使用外部晶振时这两个口不能做IO口用                                            
*  版本更新:  详见readme.txt
*
*              20110805  V1.00                                            
*                                                                                          
******************************************************************
*注意: RS/CS    PC0
*       RW/SID   PC1
*       E/SCLK   PC2
*       PSB      PC3
*       RST      PC4
*       DATA     PORTB  
******************************************************************/

#include "includes.h"

int main(void)
{
    //12864初始化
	LCD_Init();
	//清屏,全部填0
	LCD12864_DisplayCLR();

    while(1)
    {
        //汉字显示
		LCD_Pos(1,1);
		// LCD_Write_String(dis1);
		LCD_Write_String("芜湖联大");
		Delay_MS(5);
        LCD_Pos(2,1);
		// LCD_Write_String(dis2);
		LCD_Write_String("飞思卡尔工作室");
		Delay_MS(5);
		LCD_Pos(3,1);
		// LCD_Write_String(dis3);
		LCD_Write_String("20110808");
		Delay_MS(5);
		LCD_Pos(4,1);
		// LCD_Write_String(dis4);
		LCD_Write_String("庞辉");
		Delay_MS(500);
    }

    return 0;
}





#include "includes.h"


/***********************************************************
** 名称:void Delay_MS(uint16 xms)
** 功能:LCD12864驱动类延时函数
** 入口参数:xms	需要延时的毫秒数
** 出口参数:无
** 使用说明:无
**********************************************************/
void Delay_MS(uint16 xms)
{
	uint16 i,j;

	for(j=0;i<xms;j++)
    {
		for(i=0;i<1100;i++)
		{
			;
		}
    }
}

/***********************************************************
** 名称:uint8 LCD_Busy(void)
** 功能:LCD忙检测函数
** 入口参数:无
** 出口参数:result	状态值
** 使用说明:无
**********************************************************/
uint8 LCD_Busy(void)
{
	uint8 result = 0;
    uint8 temp = 0;

	Part = 0xff;
    //
    DDR_DATA = 0x00;
	LCD_RS=0;  
	LCD_RW=1;
	LCD_EN= 1;
    temp = Part_Pin;
	result=(temp & 0x80);
	LCD_EN=0;
    //
    DDR_DATA = 0xff;
	return result;
}

/***********************************************************
** 名称:void LCD_Write_Cmd(uint8 com)
** 功能:液晶写一个命令函数
** 入口参数:com	写命令值
** 出口参数:无
** 使用说明:无
**********************************************************/
void LCD_Write_Cmd(uint8 com)
{
	while(LCD_Busy());
	LCD_RS=0;  //选择指令寄存器
	LCD_RW=0;  //写
	LCD_EN=0;  
	Part=com;    //指令值赋给P0口
	//这句延迟不能丢,不然有花屏
    Delay_MS(1);
	LCD_EN=1;
	//Delay_MS(1);
	LCD_EN=0; 
}

/***********************************************************
** 名称:uint8 LCD_Read_Dat(void)
** 功能:液晶读一个字符数据函数
** 入口参数:无
** 出口参数:ReturnValue	读字符数据
** 使用说明:无
**********************************************************/
uint8 LCD_Read_Dat(void)
{
	uint8 ReturnValue;

	while(LCD_Busy());
	Part = 0xff;
    //
    DDR_DATA = 0x00;
	LCD_RS = 1;
	LCD_RW = 1;

	LCD_EN = 1;
	//Delay_MS(1);
	ReturnValue = Part_Pin;
	LCD_EN = 0;
    //
    DDR_DATA = 0xff;
	//Delay_MS(1);
	return ReturnValue;
}

/***********************************************************
** 名称:void LCD_Write_Dat(uint8 date)
** 功能:液晶写一个字符数据函数
** 入口参数:date	写字符数据
** 出口参数:无
** 使用说明:无
**********************************************************/
void LCD_Write_Dat(uint8 date)
{
	while(LCD_Busy());
	LCD_RS=1;  //选择数据寄存器
	LCD_RW=0;  //写
	LCD_EN=0;
	Part=date;    //数据值赋给P0口
	//Delay_MS(1);
	LCD_EN=1;
	//Delay_MS(1);
	LCD_EN=0;
}

/***********************************************************
** 名称:void LCD_Write_String(uint8 *str)
** 功能:液晶写一个字符串函数
** 入口参数:str	写字符串
** 出口参数:无
** 使用说明:无
**********************************************************/
void LCD_Write_String(uint8 *str)
{
	while(*str!='\0')  //未结束
	{
		LCD_Write_Dat(*str++);
		//Delay_MS(1);
	}
}

/***********************************************************
** 名称:void LCD_Pos(uint8 x,uint8 y)
** 功能:液晶显示位置函数,从第X行的第Y位置开始显示
** 入口参数:x	第x行
**			 y	第y列
** 出口参数:无
** 使用说明:无
**********************************************************/
void LCD_Pos(uint8 x,uint8 y) 
{
	 uint8 pos;

	 if(x==1)        //第一行
	 { 
	 	x=0x80;
	 }
	 else if(x==2)  //第二行
	 { 
	 	x=0x90;
	 }
	 else if(x==3)  //第三行
	 { 
	 	x=0x88;
	 }
	 else if(x==4)  //第四行
	 { 
	 	x=0x98;
	 }
	 pos=x+y-1;     //首地址为0X80
	 LCD_Write_Cmd(pos);
}

/***********************************************************
** 名称:void LCD_Init(void)
** 功能:液晶初始化函数
** 入口参数:无
** 出口参数:无
** 使用说明:无
**********************************************************/
void LCD_Init(void)
{
    DDR_RS = 1;    
    DDR_RW = 1;    
    DDR_EN = 1;    
    DDR_PSB = 1;   
    DDR_RST = 1;
    DDR_DATA = 0xff;   
    
    LCD_PSB=1;  //并行方式
    LCD_RST=1;  //不复位
    LCD_Write_Cmd(0x30);
    Delay_MS(5);
    LCD_Write_Cmd(0x0c);  //开显示,不显示光标
    Delay_MS(5);
    LCD_Write_Cmd(0x06);  //写一个字符后地址指针自动加1
    Delay_MS(5);
    LCD_Write_Cmd(0x01);   //清屏
    Delay_MS(5);
}

/**********************************************************
** 名称:GUI_Point(uint8 y,uint8 x,unsigned colour)
** 功能:在指定位置上画点。
** 入口参数:x		指定点所在行的位置
**           y		指定点所在列的位置
**          color     	显示颜色(对于黑白色LCD12864,为0时灭,为1时显示)
** 出口参数:无
** 使用说明:无
**********************************************************/

void GUI_Point(uint8 x,uint8 y,uint8 color)    
{
    uint8 Row , Tier , Tier_bit ;
    uint8 ReadOldH, ReadOldL ;
    
	
	LCD_Write_Cmd( 0x34 ) ;
    //打开绘图
	LCD_Write_Cmd(0x36);

    Tier = x >> 4 ;    
    Tier_bit = x & 0x0f;
    
	//上半屏
	if( y < 32 )
    {
        Row = y ;
    }
	//下半屏
    else
    {
        Row = y - 32 ;
        Tier += 8 ;
    }
	//垂直坐标
    LCD_Write_Cmd( Row + 0x80 );
    //水平坐标
	LCD_Write_Cmd( Tier + 0x80 );

    LCD_Read_Dat() ;
    ReadOldH = LCD_Read_Dat(); 
    ReadOldL = LCD_Read_Dat(); 
    LCD_Write_Cmd( Row + 0x80 );
    LCD_Write_Cmd( Tier + 0x80 );
    if( Tier_bit < 8 )
    {
        switch( color)
        {
            case 0 : ReadOldH &=( ~( 0x01 << ( 7 - Tier_bit ))); break ;
            case 1 : ReadOldH |= ( 0x01 << ( 7 - Tier_bit )); break ;
            case 2 : ReadOldH ^= ( 0x01 << ( 7 - Tier_bit )); break ;
            default : break;    
        }
        LCD_Write_Dat( ReadOldH );
        LCD_Write_Dat( ReadOldL );
    }
    else
    {
        switch(color)
        {
            case 0 : ReadOldL &= (~( 0x01 << ( 15 - Tier_bit ))) ; break ;
            case 1 : ReadOldL |= ( 0x01 << ( 15 - Tier_bit ))    ; break ;
            case 2 : ReadOldL ^= ( 0x01 << ( 15 - Tier_bit )) ; break ;
            default : break ;
        }
        LCD_Write_Dat( ReadOldH );
        LCD_Write_Dat( ReadOldL );
    }
	
    LCD_Write_Cmd( 0x30 );

}

/***********************************************************
** 名称:GUI_Line(uint8 x0,uint8 y0,uint8 x1,uint8 y1,uint8 colour)
** 功能:在指定位置上画线。
** 入口参数:x0		指定线起点所在行的位置
**           y0   	指定线起点所在列的位置
**           x1		指定线终点所在行的位置
**           y1   	指定线终点所在列的位置
**          color     	显示颜色(对于黑白色LCM,为0时灭,为1时显示)
** 出口参数:无
** 使用说明:无
**********************************************************/
void GUI_Line(uint8 x0,uint8 y0,uint8 x1,uint8 y1,uint8 colour)
{
    int temp;
    int dx,dy;               //定义起点到终点的横、纵坐标增加值
    int s1,s2,status,i;
    int Dx,Dy,sub;

    dx = x1 - x0;
    if(dx >= 0)                 //X的方向是增加的
        s1 = 1;
    else                     //X的方向是降低的
        s1 = -1;     
    dy = y1 - y0;                 //判断Y的方向是增加还是降到的
    if(dy >= 0)
        s2 = 1;
    else
        s2 =- 1;
  
    Dx = _abs(x1-x0);             //计算横、纵标志增加值的绝对值
    Dy = _abs(y1-y0);
       
    if(Dy > Dx)                              
    {                     //以45度角为分界线,靠进Y轴是status=1,靠近X轴是status=0 
        temp = Dx;
        Dx = Dy;
        Dy = temp;
    status = 1;
    } 
    else
        status = 0;


/*********Bresenham算法画任意两点间的直线********/ 
    sub = Dy + Dy - Dx;                 //第1次判断下个点的位置
    for(i = 0;i < Dx;i ++)
    { 
        GUI_Point(x0,y0,colour);           //画点 
        if(sub >= 0)                               
        { 
            if(status == 1)               //在靠近Y轴区,x值加1
                x0 += s1; 
            else                     //在靠近X轴区,y值加1               
                y0 += s2; 
            sub -= (Dx + Dx);                 //判断下下个点的位置 
        } 
        if(status == 1)
            y0 += s2; 
        else       
            x0 += s1; 
        sub += Dy + Dy;         
    } 
}


/***********************************************************
** 名称:void LCD12864_DisplayCLR(void)
** 功能:清屏
** 入口参数:无
** 出口参数:无
** 使用说明:无
**********************************************************/

void LCD12864_DisplayCLR(void) 
{
	uint8 i, j, k ;
	while(LCD_Busy());
	LCD_Write_Cmd(0x34);
	LCD_Write_Cmd(0x36);

	for( i = 0 ; i < 2 ; i++ )//分上下两屏写
	{
		for( j = 0 ; j < 32 ; j++ )
		{
			while(LCD_Busy());		
			LCD_Write_Cmd( 0x80 + j ) ;//写Y坐标
			Delay_MS(1);
			if( i == 0 )                    //写X坐标
			{
			    LCD_Write_Cmd( 0x80 ) ;
				Delay_MS(1);
			}
			else
			{
			    LCD_Write_Cmd( 0x88 ) ;
				Delay_MS(1);
			}
			for( k = 0 ; k < 16 ; k++ )      //写一整行数据
			{
				while(LCD_Busy());
			    LCD_Write_Dat(0x00) ;
				Delay_MS(1);
			}
		}
	}
	LCD_Write_Cmd( 0x30 ) ;
}

/****************************************************************************
** 名称:plotC(int x,int y,int xc,int yc,uint8 colour)
** 功能:八分点画圆函数
** 入口参数:x		指定线起点所在行的位置
**           y   	指定线起点所在列的位置
**          color     	显示颜色(对于黑白色LCM,为0时灭,为1时显示)
** 出口参数:无
** 使用说明:无
****************************************************************************/
void plotC(int x,int y,int xc,int yc,uint8 colour)
{
    GUI_Point(xc+x,yc+y,colour);
    GUI_Point(xc+x,yc-y,colour);
    GUI_Point(xc-x,yc+y,colour);
    GUI_Point(xc-x,yc-y,colour);
    GUI_Point(xc+y,yc+x,colour);
    GUI_Point(xc+y,yc-x,colour);
    GUI_Point(xc-y,yc+x,colour);
    GUI_Point(xc-y,yc-x,colour);
}

/****************************************************************************
** 名称:GUI_Circle(int xc,int yc,int r,uint8 colour)
** 功能:画圆
** 入口参数:xc		圆心的行坐标
**           yc   	圆心的列坐标
**           r		半径
**          color     	显示颜色(对于黑白色LCM,为0时灭,为1时显示)
** 出口参数:无
** 使用说明:无
****************************************************************************/
void GUI_Circle(int xc,int yc,int r,uint8 colour)
{
    int x,y,d;
    y = r;
    d = 3 - (r + r);
    x = 0;
    while(x <= y)
    {
        plotC(x,y,xc,yc,colour);
        if(d < 0)
            d += (x + x + x + x) + 6;
        else
        {
            d+=((x - y) + (x - y) + (x - y) + (x - y)) + 10;
            y = y - 1;
        }
        x = x + 1;
    }
}

/****************************************************************************
** 名称:GUI_Full(uint8 x0,uint8 y0,uint8 x1,uint8 y1,uint8 colour)
** 功能:用绘图的方法填充一个矩形
** 入口参数:x0		起始点横坐标
**           y0   	起始点纵坐标
**           x1		终止点横坐标
**           y1      终止点纵坐标
**          color     	显示颜色(对于黑白色LCM,为0时灭,为1时显示)
** 出口参数:无
** 使用说明:无
****************************************************************************/
void GUI_Full(uint8 x0,uint8 y0,uint8 x1,uint8 y1,uint8 colour)
{
    uint8 i,j;
	for(j = y0;j <= y1;j ++)
	    for(i = x0;i <= x1;i ++)
		    GUI_Point(i,j,colour);
}

/************************************************************************
//废弃函数区

//水平画线
void v_Lcd12864DrawLineX_f( uint8 X0, uint8 X1, uint8 Y, uint8 Color )
{    uint8 Temp ;
    if( X0 > X1 )
    {
        Temp = X1 ;
        X1 = X0 ;
        X0 = Temp ;
    }
    for( ; X0 <= X1 ; X0++ )
    GUI_Point( X0, Y, Color);    
}
//垂直画线
void v_Lcd12864DrawLineY_f( uint8 X, uint8 Y0, uint8 Y1, uint8 Color )
{
    uint8 Temp ;
    if( Y0 > Y1 )
    {
        Temp = Y1 ;
        Y1 = Y0 ;
        Y0 = Temp ;
    }
    for(; Y0 <= Y1 ; Y0++)
    GUI_Point( X, Y0, Color);
}
************************************************************************/

/******************************************************************************
**  12864 LCD模块
******************************************************************************/

#ifndef _12864_LCD_
#define _12864_LCD_

#include "math.h"

/******************************************************************************
**  宏定义
******************************************************************************/
//IO口定义

//8bit数据接入IO口
#define Part PORTB
#define Part_Pin PINB    

//控制数据端

//定义12864液晶RS端,寄存器选择信号 H:数据寄存器 L:指令寄存器
#define LCD_RS PORTC_PC0 

//定义12864液晶RW端,读/写信号  H:读   L:写  
#define LCD_RW PORTC_PC1

//定义12864液晶LCDEN端, 片选信号  下降沿触发,锁存数据   
#define LCD_EN PORTC_PC2 
  
//定义12864液晶PSB端, H:并行 L:串行
#define LCD_PSB PORTC_PC3 

//定义12864液晶RST端, H:不复位  L:复位 
#define LCD_RST PORTC_PC4 
 

//IO数据方向定义

#define DDR_DATA   DDRB
	
#define DDR_RS     DDRC_DDRC0
#define DDR_RW     DDRC_DDRC1
#define DDR_EN     DDRC_DDRC2
#define DDR_PSB    DDRC_DDRC3
#define DDR_RST    DDRC_DDRC4 

/******************************************************************************
**  全局变量声明
******************************************************************************/


/******************************************************************************
**  函数声明
******************************************************************************/


//毫秒延时函数
void Delay_MS(uint16 xms);

//LCD忙检测函数
uint8 LCD_Busy(void);

//液晶写命令函数
void LCD_Write_Cmd(uint8 com);

//液晶读命令函数
uint8 LCD_Read_Dat(void);

//液晶写一个字符数据函数
void LCD_Write_Dat(uint8 date);

//液晶写一个字符串函数
void LCD_Write_String(uint8 *str);

//液晶显示位置函数,从第X行的第Y位置开始显示
void LCD_Pos(uint8 x,uint8 y);

//液晶初始化函数
void LCD_Init();

//清屏
void LCD12864_DisplayCLR(void);

//在指定位置上画点。
void GUI_Point(uint8 x,uint8 y,uint8 color);

//在指定位置上画线。
void GUI_Line(uint8 x0,uint8 y0,uint8 x1,uint8 y1,uint8 colour);

//八分点画圆函数
void plotC(int x,int y,int xc,int yc,uint8 colour);

//画圆
void GUI_Circle(int xc,int yc,int r,uint8 colour);

//用绘图的方法填充一个矩形
void GUI_Full(uint8 x0,uint8 y0,uint8 x1,uint8 y1,uint8 colour);

#endif






  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ATmega16是一款AVR系列的单片机,以其低功耗、高性能和丰富的外设模块受到广泛的应用。而Keil是一款用于ARM微控制器开发的集成开发环境(IDE),但也支持AVR芯片的开发。 在使用Keil开发ATmega16的过程中,我们可以通过编写例程来实现不同功能。例如,我们可以设计一个LED闪烁的例程来测试开发板是否正常工作。首先,我们需要将开发板上的LED连接到ATmega16的某个IO引脚上,并在Keil中配置这个引脚为输出模式。接下来,我们可以编写一个简单的C程序,在循环中不断地改变LED的状态,从而实现闪烁的效果。 除了LED闪烁,我们还可以在Keil中编写其他例程来实现更复杂的功能。例如,我们可以设计一个ADC(模数转换器)例程,以读取模拟输入信号的数值并进行处理。我们可以使用ATmega16上的ADC模块和Keil提供的库函数,在C程序中配置ADC,并编写相应的代码来读取和处理模拟输入信号。 另外,我们还可以利用Keil编写的例程来驱动其他外设模块,如LCD显示屏、蜂鸣器、定时器等。通过学习和应用例程,我们可以更好地了解ATmega16的各种功能和特性,并且能够快速开发出自己的嵌入式系统。 总之,使用Keil编写ATmega16例程可以帮助我们简化开发过程,并且能够快速实现各种功能。结合ATmega16强大的硬件性能和Keil提供的开发工具,我们能够轻松地开发各种应用,同时也提高了开发效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值