论坛风格切换切换到宽版
  • 4748阅读
  • 13回复

求助个关于AVR的弱智问题(已经解决,附带程序) [复制链接]

上一主题 下一主题
离线永远的FM
 
发帖
12110
只看楼主 倒序阅读 0楼 发表于: 2009-01-19
在c环境中,ddrd是代表d端口的什么东西?
如果在工作中途要改变端口输入输出属性,是不是要改这个参数?
在线BG4UVR
发帖
11287
只看该作者 1楼 发表于: 2009-01-19
ddrd是d端口的方向控制寄存器,用来设置端口d是输入还是输出的。程序中途改变它是完全可以的。
离线小比尔/5
发帖
2582
只看该作者 2楼 发表于: 2009-01-19
所以一开始从51转到avr,这个特性让人甚是不爽。
还有port和pin的区别,天啊。。。

avr的端口移植和位操作都比51要麻烦。。。
离线appcat
发帖
145
只看该作者 3楼 发表于: 2009-01-19
ddrd=1,把d端口设为输出,ddrd=0,把d端口设为输入。工作中途要改变端口输入输出属性,就要修改ddrd。
在线BG4UVR
发帖
11287
只看该作者 4楼 发表于: 2009-01-19
ddrd=1

是把d0设置为输出,d7-d1设置为输入
离线永远的FM
发帖
12110
只看该作者 5楼 发表于: 2009-01-19
谢谢帮助,刚刚尝试把原来51里的1602驱动程序移植到iccavr里,结果编译出了一大堆错误。其中主要是这些:
1原来的位定义指令sbit现在好像不行了,就是说我想把portd的第0位定义为rs,请问要怎样写?
2在对函数定义时,51是这样的:
void dispchar(uchar map,uchar leng,uchar code *word);
结果软件提示
ia\单片机相关\avr程序\1602-1.c(39): syntax error; found `*' expecting `)'
!e f:\hanjia\单片机相关\avr程序\1602-1.c(39): skipping `*' `word'
好像不给用*word这种指针。
请问要如何修改?
离线radiolee
发帖
6050
只看该作者 6楼 发表于: 2009-01-19
到隔壁ourdev去搜,大把1602驱动,现成的
离线bg4kc
发帖
2638
只看该作者 7楼 发表于: 2009-01-20
我感觉我这个最简单。

#include <avr/io.h>
#include <util/delay_basic.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#define freq 11.0592

#define uint unsigned int
#define uchar unsigned char
#define lcd_en_port   portd
#define lcd_rw_port   portd
#define lcd_rs_port   portd
#define lcd_data_port portc
#define lcd_data_ddr   ddrc
#define lcd_data_pin   pinc


#define lcd_en       pd7   //portd7     out
#define lcd_rs       pd5   //portd5     out
#define lcd_data     0x0f   //portc 0/1/2/3   out
#define lcd_rw       pd6   //portd 6   out

/*--------------------------------------------------------------------------------------------------
public function prototypes
--------------------------------------------------------------------------------------------------*/
void lcd_init       (void); //初始化
void delay_nus     (unsigned int n);
void delay_nms     (unsigned int n);
void wrc                  (unsigned char x); //设定地址
void wrd                  (unsigned char x);//写字符
void dis                  (unsigned char x);//写100以内的两位数

void lcd_init(void)     //液晶初始化
{
delay_nms(15);
ddrc |= lcd_data;   // 数据为输出
ddrd |= (1<<lcd_rs); //置位rs.en
ddrd |= (1<<lcd_en);
ddrd |= (1<<lcd_rw);
lcd_rw_port &= ~(1<<lcd_rw);
wrc(0x28); //4位显示
wrc(0x0c); //显示开
wrc(0x01); //清屏
delay_nms(60);      //>40us
}

void wrd(uchar x)
{
uchar i;
lcd_rs_port |= (1<<lcd_rs); //rs=1
i = x>>4;
lcd_data_port &= 0xf0;
lcd_data_port |= i & 0x0f; //写高四位
lcd_en_write();
i = x;
lcd_data_port &= 0xf0;
lcd_data_port |= i & 0x0f;   //写低四位
lcd_en_write();
delay_nus(50);      //>40us
}
void wrc(uchar x)
{
uchar i;
lcd_rs_port &= ~(1<<lcd_rs); //rs=0
i = x>>4;
lcd_data_port &= 0xf0;
lcd_data_port |= i & 0x0f; //写高四位
lcd_en_write();
i = x;
lcd_data_port &= 0xf0;
lcd_data_port |= i & 0x0f;   //写低四位
lcd_en_write();
delay_nus(50);      //>40us
}

void lcd_en_write(void) //液晶使能
{
lcd_en_port |= (1<<lcd_en);
delay_nus(1);
lcd_en_port &= ~(1<<lcd_en);
delay_nus(1);            //这里1us足够了
}

void dis(uchar x)
{
uchar i,j;
i=(x/10)|0x30;
wrd(i);
j=(x%10)|0x30;
wrd(j);
}

void delay_nms(unsigned int ms)
{
  unsigned int i;
  for(i=0;i<ms;i++ )
  {
    _delay_loop_2(250*freq);   //16-bit count, 4 cycles/loop
  }                              
}
void delay_nus(unsigned int us)
{
  unsigned int i;
  for(i=0;i<us;i++ )
  {
    _delay_loop_2(freq/4);  
  }                
}

int main(void)
{
uchar u=3456;
delay_nms(1000);
lcd_init();
//以下在液晶上第一行写字符
wrc(0x80);
wrd('.');wrd('.');wrd('.');wrd('.');wrd('.');wrd('.');wrd('.');wrd('.');
wrd('.');wrd('.');wrd('.');wrd('.');wrd('.');wrd('.');wrd('.');wrd('.');
//以下在第二行显示3456
wrc(0xc0);
dis(u/100);dis(u%100);
while(1);
}
离线bg4kc
发帖
2638
只看该作者 8楼 发表于: 2009-01-20
四线方式的。 修改一下口线定义。保用3年。
离线永远的FM
发帖
12110
只看该作者 9楼 发表于: 2009-01-20
楼上的4线制,我贴个昨晚连夜调好的驱动程序,我自己觉得比较好用且容易理解的。在iccavr编译通过。
但是感觉对某个端口的高低电平控制比较头痛,比51麻烦多了。。。。

#include <iom8v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
#define rs pc0
#define rw pc1
#define e pc2
#define lcd_dt portd
#define lcd_code_out portc
#define rs_h     lcd_code_out |= bit(rs)
#define rs_l     lcd_code_out &= ~bit(rs)
#define rw_h     lcd_code_out |= bit(rw)
#define rw_l     lcd_code_out &= ~bit(rw)
#define e_h     lcd_code_out |= bit(e)
#define e_l     lcd_code_out &= ~bit(e)

void port_init(void)
{
portb = 0x00;
ddrb = 0x00;
portc = 0x3f; //m103 output only
ddrc = 0x3f;
portd = 0xff;
ddrd = 0xff;
}

//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
cli(); //disable all interrupts
port_init();

mcucr = 0x00;
gicr = 0x00;
timsk = 0x00; //timer interrupt sources
sei(); //re-enable interrupts
//all peripherals are now initialized
}
void lcd_init(void);//你用到什么函数,都要提前声明,不然就说你错误哦
void dispchar(uchar map,uchar leng,uchar *word);
void dispword(uchar map,uchar loc,uchar *word);
void lcd_wcmd(uchar command);
void lcd_wdat(uchar worddata);
void del(uint time);
void dell(uint time);
uchar l3[10]={"0123456789"};
uchar l2[13]={"atmega8l test"};

void main(void)//主程序开始
{
init_devices();
lcd_init();
while(1)//反复循环显示2行英文
{
dispchar(0x80,9,l3);
dispchar(0xc0,12,l2);
dell(50);
lcd_wcmd(0x01);//清屏
}
}

//------------------------------------------------------ 功能子程序
void dispchar(uchar map,uchar leng,uchar *word)//写一行字
{
uchar i=0,le=0;
for(i=0;i<=leng;i++)
{
lcd_wcmd(map);
map++;
lcd_wdat(word[le]);
le++;
}
lcd_wcmd(0x0c);
}
//-------------------------------------------------------
void dispword(uchar map,uchar loc,uchar *word) //写一个字(一般是数字)
{
lcd_wcmd(map);
lcd_wdat(word[loc]);
lcd_wcmd(0x0c);
}

//--------------------------------------------------
void lcd_wcmd(uchar command)//写地址码(写命令)
{
lcd_dt=command;
rs_l;
rw_l;
e_l;
del(50);
e_h;
}

//------------------------------------------------
void lcd_wdat(uchar worddata)//写数据子函数
{
lcd_dt=worddata;
rs_h;
rw_l;
e_l;
del(30);
e_h;
}

//-----------------------------------------------
void lcd_init(void)//初始化
{
lcd_wcmd(0x08);
lcd_wcmd(0x01);//清屏
lcd_wcmd(0x38);//显示功能
lcd_wcmd(0x0f);//显示开关控制
}
//----------------------------------------------
void del(uint time)//较短的延时
{
time*=100;
while(time--);
}
//---------------------------------------------
void dell(uint time)//较长延时(延时嵌套)
{
uchar time2;
while(time--)
{
time2=123;
while(time2--);
}
}
离线小比尔/5
发帖
2582
只看该作者 10楼 发表于: 2009-01-20
delay最好用内置的_delay_us函数(gcc),不同晶振移植才比较方便
一开始做1602的时候,我也是显示不出来,后来发现是发送速度太快(16mhz下),模块受不了
不知道为什么,在51上就注意不到这个问题,可能是at51确实太慢
按照手册加延时就ok
离线ba6iv
发帖
1293
只看该作者 11楼 发表于: 2009-01-21
发一个我写的1602模块,通过修改头文件标志可以兼容4线和8线,使用很方便。

**************1602.h******************
/***************************************************************
模块名称     : lcd1602a显示模块
处理器类型   : atmega16l
处理器时钟   : 4.000000 mhz
编译存储模式 : small
版本修订     : ver1.1
编   辑     : 胡云杰
日   期     : 2008年7月23日
说   明     :兼容1602lcd 4线和8线模式
================================================================
支持模块     :
================================================================
用法:
  lcd_init();
  lcd_write_string(列,行,"字符串");
  lcd_write_char(列,行,'字符');
---------------------------------------------------------------
下面是8线方式avr与lcd连接信息
pd3 ->rs
pd6 ->en
pd4 ->rw
pb0 ->d0
pb1 ->d1
pb2 ->d2
pb3 ->d3
pb4 ->d4
pb5 ->d5
pb6 ->d6
pb7 ->d7

下面是4线方式avr与lcd连接信息
pd3 ->rs
pd6 ->en
pd4 ->rw
pb0 ->d0
pb1 ->d1
pb2 ->d2
pb3 ->d3


要使用本驱动,改变下面配置信息即可
--------------------------------------------------------------*/
#ifndef __1602_h
#define __1602_h


//头文件包含区
//--------------------------------------------------------------
#include <iom16v.h>
#include <macros.h>

//-------------------------end----------------------------------------------------------------------


//参数配置区
//--------------------------------------------------------------

//_1602_mode = 1为8线模式 _1602_mode = 0为4线模式
#define _1602_mode                              0x01

/*---------------------*
*   常 数 宏 定 义   *
*---------------------*/
#ifndef true
  # define true       0x01
#endif
#ifndef false
  # define false       0x00
#endif

#ifndef enable
  # define enable       0x01
#endif
#ifndef disable
  # define disable     0x00
#endif

/*------------------------------------------------------------*/

# define lcd_write       0x00
# define lcd_read       0x01
# define lcd_command     0x00
# define lcd_data       0x01

#if _1602_mode
     //8线初始化
  # define lcd_cmd_init     0x38
#else
     //4线初始化
  # define lcd_cmd_init     0x28
#endif

# define lcd_cmd_dispctr   0x0c
# define lcd_cmd_cls     0x01
# define lcd_cmd_enterset   0x06
# define lcd_cmd_iconshow   0x0e
# define lcd_cmd_iconhide   0x0c

# define lcd_rs         _pd3
# define lcd_rw         _pd4
# define lcd_e           _pd6

#if _1602_mode
     //8线忙检测定义端口
  # define lcd_bf         read_pb7
#else
     //4线忙检测定义端口
  # define lcd_bf         read_pb3
#endif

# define lcd_data_port        portb
# define lcd_data_ddr        ddrb

//程序中未使用,待修订
# define lcd_ctrl_ddr            ddrd


#if _1602_mode
     /*lcd 8线方式*/
     # define lcd_setwritedata   lcd_data_ddr |= 0xff;lcd_data_port &= 0x00;
     # define lcd_setreaddata   lcd_data_ddr &= 0x00;lcd_data_port |= 0xff;
     # define lcd_senddata(a)            lcd_data_port = a;
#else
     # define lcd_setwritedata   lcd_data_ddr |= 0x0f;lcd_data_port &= 0xf0;
     # define lcd_setreaddata   lcd_data_ddr &= 0xf0;lcd_data_port |= 0x0f;
     # define lcd_sendhalfcharhigh(a) lcd_data_port &= 0xf0; lcd_data_port |= (a>>4);
     # define lcd_sendhalfcharlow(a) lcd_data_port &= 0xf0; lcd_data_port |= (a<<4>>4);
#endif


/*---------------------*
*   动 作 宏 定 义   *
*---------------------*/
# define setreadstate     lcd_setreaddata;lcd_rs = lcd_command;lcd_rw = lcd_read;
# define setread         lcd_setreaddata;lcd_rw = lcd_read;
# define setwrite       lcd_setwritedata;lcd_rw = lcd_write;
# define setcommand       lcd_rs = lcd_command;
# define setdata         lcd_rs = lcd_data;

# define print(a)       lcddisplaystring(a);
# define locate(x,y)     lcdsetxy(x-1,y-1);
# define cls           lcdwaitforready();lcd_write_command(lcd_cmd_cls);
# define printn(a,b)     lcddisplaynum((unsigned long)a,b);
# define showicon       lcdwaitforready();lcd_write_command(lcd_cmd_iconshow);
# define hideicon       lcdwaitforready();lcd_write_command(lcd_cmd_iconhide);

# define lcd_light                              ddrc |= 0x80;portc &= 0x7f;
# define lcd_dark                                    ddrc |= 0x80;portc |= 0x80;


/***********************
*   全局变量声明区   *
***********************/
extern const char chr[16];

//-----------------------end---------------------------------------------------------------



/*--------------------------------------------------------------------------------------------------
全局函数声明
--------------------------------------------------------------------------------------------------*/
extern void lcd_init(void);
extern void lcdwaitforready(void);
extern void lcd_write_command(unsigned char command) ;
extern void lcd_write_data(unsigned char data);
extern void lcd_set_xy (unsigned char x, unsigned char y);
extern void lcd_write_string(unsigned char x,unsigned char y,unsigned char *s);
extern void lcd_write_char(unsigned char x,unsigned char y,unsigned char data);
extern void lcddisplaystring(unsigned char *string);
extern void lcddisplayword(unsigned char word);
extern void lcddisplaynum(unsigned long num,char bitcount);

//-----------------------end---------------------------------------------------------------





#endif
*********************************************



******************1602.c**********************
/***************************************************************
模块名称     : lcd1602a显示模块
处理器类型   : atmega16l
处理器时钟   : 4.000000 mhz
编译存储模式 : small
版本修订     : ver1.1
编   辑     : 胡云杰
日   期     : 2008年7月23日
说   明     :兼容1602lcd 4线和8线模式
================================================================
用法:
  lcd_init();
  lcd_write_string(列,行,"字符串");
  lcd_write_char(列,行,'字符');
---------------------------------------------------------------
下面是8线方式avr与lcd连接信息
pd3 ->rs
pd6 ->en
pd4 ->rw
pb0 ->d0
pb1 ->d1
pb2 ->d2
pb3 ->d3
pb4 ->d4
pb5 ->d5
pb6 ->d6
pb7 ->d7

下面是4线方式avr与lcd连接信息
pd3 ->rs
pd6 ->en
pd4 ->rw
pb0 ->d0
pb1 ->d1
pb2 ->d2
pb3 ->d3


要使用本驱动,改变lcd1602.h配置信息即可
--------------------------------------------------------------*/
//头文件包含区
//--------------------------------------------------------------
#include "lcd1602.h"

//-------------------------end----------------------------------------------------------------------



/***********************
*   全局变量声明区   *
***********************/
const char chr[16] = {Ɔ',Ƈ',ƈ',Ɖ',Ɗ',Ƌ',ƌ',ƍ',Ǝ',Ə','a','b','c','d','e','f'};


//-------------------------end----------------------------------------------------------------------

/*--------------------------------------------------------------------------------------------------
局部函数声明
--------------------------------------------------------------------------------------------------*/
static void delay_1us(void);           //1us延时函数
static void delay_nus(unsigned int n);     //n us延时函数
static void delay_1ms(void);           //1ms延时函数
static void delay_nms(unsigned int n);     //n ms延时函数
//-----------------------end---------------------------------------------------------------


/*--------------------------------------------------------------------------------------------------
全局函数声明
--------------------------------------------------------------------------------------------------*/
extern void lcd_init(void);
extern void lcdwaitforready(void);
extern void lcd_write_command(unsigned char command) ;
extern void lcd_write_data(unsigned char data);
extern void lcd_set_xy (unsigned char x, unsigned char y);
extern void lcd_write_string(unsigned char x,unsigned char y,unsigned char *s);
extern void lcd_write_char(unsigned char x,unsigned char y,unsigned char data);
extern void lcddisplaystring(unsigned char *string);
extern void lcddisplayword(unsigned char word);
extern void lcddisplaynum(unsigned long num,char bitcount);

//-----------------------end---------------------------------------------------------------



/*--------------------------------------------------------------------------------------------------
局部函数
--------------------------------------------------------------------------------------------------*/
static void delay_1us(void)           //1us延时函数
{
  asm("nop");
}

static void delay_nus(unsigned int n)     //n us延时函数
{
  unsigned int i=0;
  for (i=0;i<n;i++)
  delay_1us();
}

static void delay_1ms(void)           //1ms延时函数
{
  unsigned int i;
  for (i=0;i<1140;i++);
}

static void delay_nms(unsigned int n)     //n ms延时函数
{
  unsigned int i=0;
  for (i=0;i<n;i++)
  delay_1ms();
}


//------------------------------end-----------------------------------------------------------------



/*--------------------------------------------------------------------------------------------------
全局函数
--------------------------------------------------------------------------------------------------*/

/********************************************************
* 函数说明:lcd初始化函数                     *
* 入口参数:                             *
* 返回参数:                             *
********************************************************/
void lcd_init(void)       //液晶初始化
{
     lcd_data_ddr = 0xff;                  //lcd端口初始化
     lcd_data_port = 0x00;
     lcd_ctrl_ddr      = 0x78;
     lcd_rs                    = 0x00;
     lcd_rw                    = 0x00;
     lcd_e                    = 0x00;
     
     lcd_light                        //点亮lcd背光
     
     delay_nms(10);
     
     lcdwaitforready();
     lcd_write_command(lcd_cmd_init);
     
     lcdwaitforready();
     lcd_write_command(lcd_cmd_dispctr);
     
     lcdwaitforready();
     lcd_write_command(lcd_cmd_cls);
     delay_nms(10);
     lcd_write_command(lcd_cmd_enterset);
     

}


/********************************************************
* 函数说明:                             *
* 入口参数:                             *
* 返回参数:                             *
********************************************************/
void lcd_write_command(unsigned char command) //写指令
{
     setwrite;
     setcommand;
     
     #if _1602_mode
           lcd_e = enable;                                                      //8线方式
           lcd_senddata(command);
           lcd_e = disable;
     #else
           lcd_e = enable;                                                      //4线方式
           lcd_sendhalfcharhigh(command);
           lcd_e = disable;
     
           lcd_e = enable;
           lcd_sendhalfcharlow(command);
           lcd_e = disable;
     #endif
     
     setread;            
     setcommand;

}


/********************************************************
* 函数说明:                             *
* 入口参数:                             *
* 返回参数:                             *
********************************************************/
void lcd_write_data(unsigned char data) //写数据
{
setwrite;
     setdata;
     
     #if _1602_mode
           lcd_e = enable;                                                      //8线方式
           lcd_senddata(data);
           lcd_e = disable;
     #else
           lcd_e = enable;                                                      //4线方式
           lcd_sendhalfcharhigh(data);
           lcd_e = disable;
     
           lcd_e = enable;
           lcd_sendhalfcharlow(data);
           lcd_e = disable;
     #endif
     
     setread;            
     setcommand;
}


/********************************************************
* 函数说明:等待lcd空闲状态函数                 *
* 入口参数:                             *
* 返回参数:                             *
********************************************************/
void lcdwaitforready(void)
{
  //delayus(30);
     setread;
     setcommand;
 
  lcd_e = enable;  
 
     while (lcd_bf == enable);   //rw=1,读pd7,为0表示空闲;
 
  lcd_e = disable;
}


/********************************************************
* 函数说明:                             *
* 入口参数:                             *
* 返回参数:                             *
********************************************************/
void lcd_set_xy( unsigned char x, unsigned char y ) //写地址函数
{
  unsigned char address;
  if (y == 0)
     {
        address = 0x80 + x;
     }
  else
     {
    address = 0xc0 + x;
     }
     
     lcdwaitforready();
  lcd_write_command(address);
}


/********************************************************
* 函数说明:                             *
* 入口参数:                             *
* 返回参数:                             *
********************************************************/
void lcd_write_string(unsigned char x,unsigned char y,unsigned char *s) //列x=0~15,行y=0,1
{
  lcd_set_xy( x, y ); //写地址  
  while(*s)
     {
        lcdwaitforready();
        lcd_write_data(*s);
           s++;
     }
   
}


/********************************************************
* 函数说明:                             *
* 入口参数:                             *
* 返回参数:                             *
********************************************************/
void lcd_write_char(unsigned char x,unsigned char y,unsigned char data) //列x=0~15,行y=0,1
{
lcd_set_xy( x, y ); //写地址
lcdwaitforready();
lcd_write_data(data);

}


/********************************************************
* 函数说明:lcd字符串显示函数                 *
* 入口参数:                             *
* 返回参数:                             *
********************************************************/
void lcddisplaystring(unsigned char *string)
{
  while(*string)
     {
        lcdwaitforready();
        lcd_write_data(*string);
           string++;
     }
}


/********************************************************
* 函数说明:lcd字符显示函数                   *
* 入口参数:                             *
* 返回参数:                             *
********************************************************/
void lcddisplayword(unsigned char word)
{
 
     lcdwaitforready();
     lcd_write_data(word);
     
}



/********************************************************
* 函数说明:数值显示函数(hex 16进制显示)           *
* 入口参数:需要显示的数字(无符号长整形)         *
* 返回参数:                             *
********************************************************/
void lcddisplaynum(unsigned long num,char bitcount)
{
char a = 0;
     for (a = 8-bitcount ;a<8;a++)
     {
        lcd_write_data(chr[(num<<(a<<2))>>28]);
     }
}

//--------------------------------------end---------------------------------------------------------
离线BG7IRP
发帖
3596
只看该作者 12楼 发表于: 2009-08-09
不错!学习了
发帖
689
只看该作者 13楼 发表于: 2009-08-17
楼猪太密密麻麻啦
眼花啦
这东西要的话
网上很多