打印
[AVR单片机]

AVR入门求帮助

[复制链接]
1423|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Channe|  楼主 | 2012-7-31 21:59 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
电路图是这样


程序是这样
/*
KS0108 128*64 LCD C语言驱动
参考ICCAVR资料和网上的资料改写
LCD引脚定义
1---GND
2---VCC
3---VLCD
4---D/I
5---R/W
6---E
7到14 D0-D7
15--CS1
16--CS2
17--RESET
18--VEE
19--SW
20--NC
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#define CLI cli
#define SEI sei
#define BIT(A) (1<<A)

/* 当前行、列存储,行高16点,列宽8点 */
unsigned char CurOffset,CurRow,CurPage,CurCol;


/*  常量定义  */
#define LCD_STATUS_BUSY 0x80
#define  START_LINE0   0xc0
#define  DISPLAY_ON    0x3f
#define  DISPLAY_OFF   0x3e
#define  PARA1         0x40
//PORTA---数据口  PORTB----控制口
#define LCD_DIR_PORT
DDRA
#define LCD_IP_PORT
PINA
#define LCD_OP_PORT
PORTA

#define LCD_EN_PORT
PORTD
#define LCD_CS2_PORT
PORTD
#define LCD_CS1_PORT
PORTD
#define LCD_RW_PORT
PORTD
#define LCD_DI_PORT
PORTD

#define LCD_DI_BIT
BIT(7)//0x80
#define LCD_RW_BIT
BIT(6)//0x40
#define LCD_EN_BIT
BIT(5)//0x20
#define LCD_CS1_BIT
BIT(4)//0x10
#define LCD_CS2_BIT
BIT(3)//0x08

#define SET_LCD_E
LCD_EN_PORT |= LCD_EN_BIT    //LCD使能
#define CLEAR_LCD_E
LCD_EN_PORT &= ~LCD_EN_BIT   //LCD禁止

#define SET_LCD_DATA
LCD_DI_PORT |= LCD_DI_BIT    //选择指令端口
#define SET_LCD_CMD
LCD_DI_PORT &= ~LCD_DI_BIT   //选择数据端口

#define SET_LCD_READ
LCD_RW_PORT |= LCD_RW_BIT    //读模式
#define SET_LCD_WRITE
LCD_RW_PORT &= ~LCD_RW_BIT   //写模式

#define SET_LCD_CS2     LCD_CS2_PORT |= LCD_CS2_BIT  //左屏选择禁止
#define CLEAR_LCD_CS2   LCD_CS2_PORT &= ~LCD_CS2_BIT //左屏选择使能

#define SET_LCD_CS1     LCD_CS1_PORT |= LCD_CS1_BIT  //左屏选择禁止
#define CLEAR_LCD_CS1   LCD_CS1_PORT &= ~LCD_CS1_BIT //左屏选择使能

#define LEFT 0
#define RIGHT 1
#define CMD 0
#define DATA 1

void LCD_BUSY(unsigned char lr) //判断忙标志
{

unsigned char status;
    CLI();

if(lr==LEFT)

{

    CLEAR_LCD_CS2; //cs2=0

SET_LCD_CS1;   //cs1=1

}

else

{

SET_LCD_CS2;   //cs2=1
   
CLEAR_LCD_CS1; //cs1=0

}


SET_LCD_CMD;
    LCD_DIR_PORT = 0x00;
    LCD_OP_PORT = 0x00;

    SET_LCD_READ;
    SET_LCD_E;

    asm("nop");
asm("nop");
    asm("nop");
asm("nop");
    while((LCD_IP_PORT) & LCD_STATUS_BUSY)
    {
        CLEAR_LCD_E;
   


asm("nop");
asm("nop");

asm("nop");
asm("nop");

SET_LCD_E;

asm("nop");
asm("nop");

asm("nop");
asm("nop");
    }
    CLEAR_LCD_E;
    SET_LCD_WRITE;
    LCD_OP_PORT = 0xff;
    SEI();
}

void write_LCD(unsigned char lr,unsigned char cd,unsigned char data) /*写入指令或数据*/
{

    CLI();

LCD_BUSY(lr);

if(cd==CMD)
SET_LCD_CMD;

else SET_LCD_DATA;
    SET_LCD_WRITE;

SET_LCD_E;
    LCD_DIR_PORT = 0xff;
    LCD_OP_PORT = data;
    asm("nop");
asm("nop");

asm("nop");
asm("nop");
    CLEAR_LCD_E;
    LCD_OP_PORT = 0xff;
    SEI();
}
unsigned char read_LCD(unsigned char lr)
  /*  读显示数据 */
{

unsigned char data;

    CLI();

LCD_BUSY(lr);

SET_LCD_DATA;
    LCD_DIR_PORT = 0x00;
    LCD_OP_PORT = 0xff;
    SET_LCD_READ;

SET_LCD_E;

asm("nop");
asm("nop");
    asm("nop");
asm("nop");
    data=LCD_IP_PORT;
    CLEAR_LCD_E;
    SET_LCD_WRITE;


LCD_BUSY(lr);

SET_LCD_DATA;
    LCD_DIR_PORT = 0x00;
    LCD_OP_PORT = 0xff;
    SET_LCD_READ;

SET_LCD_E;
    asm("nop");
asm("nop");

asm("nop");
asm("nop");
    data=LCD_IP_PORT;
    CLEAR_LCD_E;
    SET_LCD_WRITE;

    SEI();

return data;
}

void set_start_line_L(unsigned char line) /*设置显示起始行*/ //0-63
{

write_LCD(LEFT,CMD,0xc0|line);
}

void set_start_line_R(unsigned char line) /*设置显示起始行*/ //0-63
{

write_LCD(RIGHT,CMD,0xc0|line);
}

void set_page_L(unsigned char page)
/*设置X地址 设置页*/  //0-7
{

write_LCD(LEFT,CMD,0xb8|page);                     
}
void set_page_R(unsigned char page)
/*设置X地址 设置页*/ //0-7
{

write_LCD(RIGHT,CMD,0xb8|page);                     
}

void set_col_addr_L(unsigned char col) /*设置Y地址*/ //0-63
{

write_LCD(LEFT,CMD,0x40|col);                     
}

void set_col_addr_R(unsigned char col) /*设置Y地址*/ //0-63
{

write_LCD(RIGHT,CMD,0x40|col);                     
}

void init_lcd(void) /*初始化函数*/
{

set_start_line_L(0); /*显示起始行为0*/

set_start_line_R(0); /*显示起始行为0*/

write_LCD(LEFT,CMD,DISPLAY_ON); /*  开显示  */

write_LCD(RIGHT,CMD,DISPLAY_ON); /*  开显示  */
}

void clr_lcd(void) /*清屏函数*/
{

unsigned char pages,i;

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

{

set_page_L(pages);  /* X 页地址 */

set_page_R(pages);  /* X 页地址 */

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

{

set_col_addr_L(i);//Y

set_col_addr_R(i);//Y

write_LCD(LEFT,DATA,0x0);

write_LCD(RIGHT,DATA,0x0);

}

}
}

/*************************************/
/*             绘点函数              */
/*************************************/

void pixel(unsigned char xx,unsigned char yy,unsigned char flag)
{

unsigned int y,ch;

ch=yy%8;  //余数


y=1;

for(;ch!=0;)

{

y=y*2;

ch--;

}

if(xx<64)

{

set_page_L(yy/8);

set_col_addr_L(xx);


ch=read_LCD(LEFT);

set_col_addr_L(xx);

if(flag)

write_LCD(LEFT,DATA,ch|y);

else

{

y=~y;

ch&=y;

write_LCD(LEFT,DATA,ch|y);

}

}

else

{

set_page_R(yy/8);

set_col_addr_R(xx-64);


ch=read_LCD(RIGHT);

set_col_addr_R(xx-64);


if(flag)

write_LCD(RIGHT,DATA,ch|y);

else

{

y=~y;

ch&=y;

write_LCD(RIGHT,DATA,ch|y);

}

}
}

//ASCII 字模宽度及高度
#define ASC_CHR_WIDTH
8
#define ASC_CHR_HEIGHT
12

struct typFNT_ASC16
/* 汉字字模显示数据结构 */
{

unsigned char Index[1];

char Msk[16];
};
struct typFNT_ASC16 const ASC_16[] = {
/* 显示为8*16  Curier 10 常规*/
{'1',0x00,0x00,0x08,0x08,0xFC,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x07,0x04,0x04,0x00},
{'2',0x00,0x00,0x08,0x04,0x84,0x44,0x38,0x00,0x00,0x00,0x06,0x05,0x04,0x04,0x04,0x00},
{'3',0x00,0x00,0x08,0x04,0x44,0x44,0xB8,0x00,0x00,0x00,0x02,0x04,0x04,0x04,0x03,0x00},
{'4',0x00,0x00,0x80,0x60,0x18,0xFC,0x00,0x00,0x00,0x00,0x01,0x01,0x05,0x07,0x05,0x00},
{'5',0x00,0x00,0x7C,0x44,0x44,0x44,0x84,0x00,0x00,0x00,0x02,0x04,0x04,0x04,0x03,0x00},
{'6',0x00,0x00,0xF0,0x48,0x44,0x44,0x80,0x00,0x00,0x00,0x03,0x04,0x04,0x04,0x03,0x00},
{'7',0x00,0x00,0x0C,0x04,0x84,0x64,0x1C,0x00,0x00,0x00,0x00,0x06,0x01,0x00,0x00,0x00},
{'8',0x00,0x00,0xB8,0x44,0x44,0x44,0xB8,0x00,0x00,0x00,0x03,0x04,0x04,0x04,0x03,0x00},
{'9',0x00,0x00,0x38,0x44,0x44,0x44,0xF8,0x00,0x00,0x00,0x00,0x04,0x04,0x02,0x01,0x00},
{'0',0x00,0x00,0xF8,0x04,0x04,0x04,0xF8,0x00,0x00,0x00,0x03,0x04,0x04,0x04,0x03,0x00},
{'.',0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x00,0x00,0x00},
{':',0x00,0x00,0x00,0x0C,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x00,0x00},
{' ',0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{'(',0x00,0x00,0x00,0xE0,0x18,0x04,0x00,0x00,0x00,0x00,0x00,0x03,0x0C,0x10,0x00,0x00},
{')',0x00,0x00,0x00,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x00,0x10,0x0C,0x03,0x00,0x00},
};

#define ASC_HZ_WIDTH
12
//#define ASC_HZ_HEIGHT
12

struct typFNT_GB16
/*12*16 汉字字模显示数据结构 */
{

unsigned char Index[2];

char Msk[24];
};
struct typFNT_GB16 const GB_16[] = {
/* 宋体 9小五 显示为12*16 */
"液",0x19,0xE2,0x14,0x42,0xF2,0x2E,0x72,0x8F,0xAA,0x7A,0x02,0x00,0x01,0x07,0x00,0x00,0x07,0x04,0x04,0x02,0x01,0x02,0x04,0x00,
"晶",0x00,0xC0,0x40,0x5F,0xD5,0x15,0xD5,0x55,0x5F,0x40,0xC0,0x00,0x00,0x07,0x05,0x05,0x07,0x00,0x07,0x05,0x05,0x05,0x07,0x00,
"显",0x00,0x40,0x9F,0x15,0xD5,0x15,0xD5,0x15,0x1F,0xC0,0x00,0x00,0x04,0x04,0x05,0x04,0x07,0x04,0x07,0x06,0x05,0x04,0x04,0x00,
"示",0x10,0x12,0x92,0x52,0x12,0xF2,0x12,0x12,0x53,0x92,0x10,0x00,0x02,0x01,0x00,0x04,0x04,0x07,0x00,0x00,0x00,0x00,0x03,0x00,
"的",0xFC,0x44,0x46,0x45,0xFC,0x10,0x2C,0xC7,0x04,0x04,0xFC,0x00,0x07,0x02,0x02,0x02,0x07,0x00,0x00,0x04,0x04,0x04,0x03,0x00,
"第",0x04,0xEA,0xAB,0xAE,0xAA,0xFC,0xAA,0xAB,0xAE,0xBA,0x82,0x00,0x04,0x04,0x02,0x01,0x00,0x07,0x00,0x02,0x02,0x02,0x01,0x00,
"一",0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x30,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
"行",0x48,0x24,0xF3,0x08,0x09,0x09,0x09,0x09,0xF9,0x09,0x08,0x00,0x00,0x00,0x07,0x00,0x00,0x04,0x04,0x04,0x07,0x00,0x00,0x00,
"二",0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x04,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,
"三",0x00,0x02,0x22,0x22,0x22,0x22,0x22,0x22,0x23,0x02,0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x04,0x00,
"四",0x00,0xFF,0x81,0x41,0x3F,0x01,0x01,0xFF,0x81,0x81,0xFF,0x00,0x00,0x07,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x07,0x00,
"五",0x00,0x11,0x11,0x91,0x7F,0x11,0x11,0x11,0xF1,0x01,0x00,0x00,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x00,

};

unsigned char GetPage(void) /*得到当前页*/
{

return CurPage;
}

unsigned char GetCol(void) /*得到当前列*/
{

return CurCol;
}

void SetPageCol(unsigned char upage, unsigned char ucol) /* 设置液晶的页和列 */
{

CurPage = upage;

CurCol = ucol;

if(ucol<64)

{

set_page_L(upage);

set_col_addr_L(ucol);

}

else

{

set_page_R(upage);

set_col_addr_R(ucol-64);

}
}

/* 设置当前显示的页和列 */
void SetRowCol(unsigned char urow, unsigned char ucol)
{

unsigned char page;

CurRow = urow;

CurCol = ucol;



switch(urow)

{

case 1:

page=0;

CurOffset=1;

break;

case 2:

page=1;

CurOffset=2;

break;

case 3:

page=3;

CurOffset=1;

break;

case 4:

page=4;

CurOffset=2;

break;

case 5:

page=6;

CurOffset=1;

break;

}

SetPageCol(page,ucol);
}

void disp_char(unsigned char c)
{

unsigned char k,j,uPage,uCol,ch_r,ch_w;

unsigned char width;

unsigned char len;

uPage = GetPage();

uCol = GetCol();

len=sizeof(ASC_16)/sizeof(ASC_16[0]);

for(k=0;k<len;k++)

{

if(c == ASC_16[k].Index[0] ) break;

}

if(k<len)

{



if(c=='-'||c==':')

width=ASC_CHR_WIDTH-2;

else if(c=='|')

width=ASC_HZ_WIDTH-ASC_CHR_WIDTH;

else

width=ASC_CHR_WIDTH;



if(CurOffset==1) //下半部是写半个字节

{

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

{

SetPageCol(uPage,uCol+j);

ch_w=ASC_16[k].Msk[j];

if(uCol+j<64)
write_LCD(LEFT,DATA,ch_w);

else write_LCD(RIGHT,DATA,ch_w);

}

SetPageCol(uPage+1,uCol);



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

{

SetPageCol(uPage+1,uCol+j);

if(uCol+j<64) ch_r=read_LCD(LEFT);

else ch_r=read_LCD(RIGHT);

ch_r&=0xf0;

ch_w=ASC_16[k].Msk[ASC_CHR_WIDTH+j]&0x0f;

ch_w|=ch_r;

SetPageCol(uPage+1,uCol+j);

if(uCol+j<64)
write_LCD(LEFT,DATA,ch_w);

else write_LCD(RIGHT,DATA,ch_w);

}

}

else //上半部是写半个字节

{

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

{

SetPageCol(uPage,uCol+j);

if(uCol+j<64) ch_r=read_LCD(LEFT);

else ch_r=read_LCD(RIGHT);

ch_r&=0x0f;

ch_w=ASC_16[k].Msk[j];

ch_w=ch_w<<4;

ch_w|=ch_r;

SetPageCol(uPage,uCol+j);

if(uCol+j<64)
write_LCD(LEFT,DATA,ch_w);

else write_LCD(RIGHT,DATA,ch_w);

}

SetPageCol(uPage+1,uCol);

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

{

SetPageCol(uPage+1,uCol+j);



ch_r=ASC_16[k].Msk[j];

ch_w=ASC_16[k].Msk[ASC_CHR_WIDTH+j];

ch_r=ch_r>>4;

ch_w=ch_w<<4;

ch_w|=ch_r;

SetPageCol(uPage+1,uCol+j);

if(uCol+j<64)
write_LCD(LEFT,DATA,ch_w);

else write_LCD(RIGHT,DATA,ch_w);

}

}

}

SetPageCol(uPage,uCol+width);
}


void disp_hz(unsigned char const *hz)
{

unsigned char k,j,uPage,uCol,ch_r,ch_w;

uPage = GetPage();

uCol = GetCol();

for(k=0;k<sizeof(GB_16)/sizeof(GB_16[0]);k++)

{

if(hz[0] == GB_16[k].Index[0] && hz[1] == GB_16[k].Index[1])

break;

}


if(CurOffset==1)

{

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

{

SetPageCol(uPage,uCol+j);

ch_w=GB_16[k].Msk[j];

if(uCol+j<64)
write_LCD(LEFT,DATA,ch_w);

else write_LCD(RIGHT,DATA,ch_w);

}

SetPageCol(uPage+1,uCol);


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

{

SetPageCol(uPage+1,uCol+j);

if(uCol+j<64) ch_r=read_LCD(LEFT);

else ch_r=read_LCD(RIGHT);

ch_r&=0xf0;

ch_w=GB_16[k].Msk[ASC_HZ_WIDTH+j]&0x0f;

ch_w|=ch_r;

SetPageCol(uPage+1,uCol+j);

if(uCol+j<64)
write_LCD(LEFT,DATA,ch_w);

else write_LCD(RIGHT,DATA,ch_w);

}

SetPageCol(uPage,uCol+ASC_HZ_WIDTH);

}


else //汉字上半部是写半个字节

{

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

{

SetPageCol(uPage,uCol+j);

if(uCol+j<64) ch_r=read_LCD(LEFT);

else ch_r=read_LCD(RIGHT);

ch_r&=0x0f;

ch_w=GB_16[k].Msk[j];

ch_w=ch_w<<4;

ch_w|=ch_r;

SetPageCol(uPage,uCol+j);

if(uCol+j<64)
write_LCD(LEFT,DATA,ch_w);

else write_LCD(RIGHT,DATA,ch_w);

}

SetPageCol(uPage+1,uCol);

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

{

SetPageCol(uPage+1,uCol+j);


ch_r=GB_16[k].Msk[j];

ch_w=GB_16[k].Msk[ASC_HZ_WIDTH+j];

ch_r=ch_r>>4;

ch_w=ch_w<<4;

ch_w|=ch_r;

SetPageCol(uPage+1,uCol+j);

if(uCol+j<64)
write_LCD(LEFT,DATA,ch_w);

else write_LCD(RIGHT,DATA,ch_w);

}

SetPageCol(uPage,uCol+ASC_HZ_WIDTH);

}
}

void disp_str(unsigned char *p)
{

unsigned char i=0;

while(p>0)

{

if(p < 127)

{
/* ASCII */

disp_char(p);

}

else

{
/* 中文 */

disp_hz(&p);

i++;

}

i++;

}
}
void main()
{
unsigned char i;
DDRD=0xFF;
DDRA=0xFF;

init_lcd();
clr_lcd();
for(i=0;i<128;i++) pixel(i,63,1);
for(i=0;i<64;i++) pixel(127,i,1);
for(i=0;i<128;i++) pixel(i,0,1);
for(i=0;i<64;i++) pixel(0,i,1);
SetRowCol(1,1);
disp_str("液晶显示的第二行123");
SetRowCol(2,1);
disp_str("液晶显示的第二行345");
SetRowCol(3,1);
disp_str("液晶显示的第三行456");
SetRowCol(4,1);
disp_str("液晶显示的第四行678");
SetRowCol(5,1);
disp_str("液晶显示的第五行789");




while(1)

{

asm("nop");

}

}



AVR stdio 编译 调试
程序一直等待在Busy 那里
求帮助

相关帖子

沙发
Channe|  楼主 | 2012-7-31 22:00 | 只看该作者
仿真是可以用的

使用特权

评论回复
板凳
申小林一号| | 2012-8-1 00:19 | 只看该作者
我也好想学,可惜没有板子……有没有啥活动啊?

使用特权

评论回复
地板
Channe|  楼主 | 2012-8-1 20:49 | 只看该作者
没有人做过么

使用特权

评论回复
5
09电气| | 2012-8-12 12:27 | 只看该作者
不建议把这么长的程序贴上来,没什么人会全看的。贴程序的话就贴关键的部分吧

使用特权

评论回复
6
NE5532| | 2012-8-12 21:30 | 只看该作者
1.用仿真,对初学者不利,要用实物。
2.写这么长的程序才来调试?我都不敢。

楼主搜“侃单片机”精华帖里的“程序调试黑宝书”,看看程序应该怎么写。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:axb.me

0

主题

16

帖子

0

粉丝