首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

初学,程序中有地方不懂,请帮帮忙

初学,程序中有地方不懂,请帮帮忙

今天看了一个例程,nios2中用c实现一个电子钟.

c是大概是这样的#include <stdio.h>
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include <unistd.h>
#include "sys/alt_irq.h"
#include "alt_types.h"
#include "LCD.h"//
自己设计的头文件


static volatile alt_u8 hour;
static volatile alt_u8 minute;
static volatile alt_u8 second;
static volatile alt_u16 year;
static volatile alt_u8 month;
static volatile alt_u8 day;
static volatile alt_u8 max_day;
static int flag;
static int begin;
static alt_u8 str1[17];
static alt_u8 str2[17];
volatile int edge_capture;
 alt_u8 Tyear, Hyear, Dyear, Nyear;

static void last_day(){
  if(month==4||month==5||month==9||month==11)
    max_day=30;
  else if(month==2){
    if((year%4==0&&year%100!=0)||year%400==0)
      max_day=29;
    else
      max_day=28;
  }
  else
    max_day=31;  
}

static void handle_button_interrupts(void* context, alt_u32 id){
  volatile int* edge_capture_ptr=(volatile int*)context;
  *edge_capture_ptr=IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE);
  IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE,0);  
}

static void init_button_pio(){
  void* edge_capture_ptr=(void*)&edge_capture;
  IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTON_PIO_BASE,0xf);
  IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE,0x0);
  alt_irq_register(BUTTON_PIO_IRQ,edge_capture_ptr,handle_button_interrupts);
}


void LCD_Init()//lcd初始化
{
  lcd_write_cmd(LCD_DISPLAY_BASE,0x38); //lcd_write_cmd
在头文件"LCD.h"中对应IOWR(base, 0, data)
  usleep(2000);
  lcd_write_cmd(LCD_DISPLAY_BASE,0x0C);
  usleep(2000);
  lcd_write_cmd(LCD_DISPLAY_BASE,0x01);
  usleep(2000);
  lcd_write_cmd(LCD_DISPLAY_BASE,0x06);
  usleep(2000);
  lcd_write_cmd(LCD_DISPLAY_BASE,0x80);
  usleep(2000);
}

.......

.......

static void handle_button_press(){
  if(flag==0){
    switch(edge_capture){
    case 0x1:
    timer_set();
    display_time1();
    usleep(500000);
    display_time();
    break;
    case 0x2:
    display_day();
    break;
    case 0x4:
    display_time();
    break;
    default:
    display_time();
    break;
    }
  }

........

........

int main()
{
  init_button_pio();
  LCD_Init();
  initial_time();
  while(1){
    if(begin==0){  
    usleep(1000000);
    second++;
    if(second>=60){
      second=0;
      minute++;
    }
    if(minute>=60){
      minute=0;
      hour++;
    }
    if(hour>=24){
      hour=0;
      day++;
    }
    last_day();
    if(day>max_day){
      day=1;
      month++;
      last_day();
    }
    if(month>12){
      day=1;     
      year++;
    }
     } 
     if(edge_capture!=0){
      handle_button_press(); 
     }
     else{
      if(flag==3||flag==4||flag==5||flag==6)
        display_day();
      else
        display_time();
     }
  }

我想问一下:以上程序中标红色的那些字

1.(void LCD_Init)应该是为了在对lcd初始化中实现某项功能吧??

这些数对应的是什么功能呢?或者比如我自己要写程序时哪里能查到??我查了altra的几个文档都没有说明啊

2.(void handle_button_press)应该是edge_capture在电路板上按下不同按键时捕获的值吧??

哪里说明的那几个按键对应的是这几个数字??

小弟初学,请帮帮忙

谢谢了!!

1、LCD_Init中的红字是初使化的命令字,具体是什么功能,要看你用的LCD是什么控制器(如SED1335、ST7920等),你可以看一下LCD控制芯片的型号,查后在网上查找它的datasheet(www.alldatasheet.com),手册里有对它的包括命令在内的详细说明。这个不是在altera的文件中查。

2、edge_capture是捕获的按键值,具体对应哪个键,我给你打个比方:

假设你的板上有四个键:Button3,Button2,Button1,Button0为别对应PIO中的key[3],key[2],key[1],key[0],如果你按下Button0,则key[0]为1,key[3..1]为0,所以key就为b(0001)=h(0x01),同样
按Button1,key[1]为1,key[3..2]和key[0]为0,key就为b(0010)=h(0x02),

如果按下两个,如Button1,Button0,则,key:b(0011)=h(0x03)

以无法为有法,以无限为有限。

谢谢楼上

第二个问题明白了

第一个问题我用的实验箱没给出具体lcd的型号,难道是通用的那种?郁闷,不过倒是给了5个不同型号lcd的datasheet.....晕

还有一个问题请教:

还是那个程序中

void LCD_Init()
{
  lcd_write_cmd(LCD_DISPLAY_BASE,0x38);
  usleep(2000);
  lcd_write_cmd(LCD_DISPLAY_BASE,0x0C);
  usleep(2000);
  lcd_write_cmd(LCD_DISPLAY_BASE,0x01);
  usleep(2000);
  lcd_write_cmd(LCD_DISPLAY_BASE,0x06);
  usleep(2000);
  lcd_write_cmd(LCD_DISPLAY_BASE,0x80);
  usleep(2000);
}

....

....

static void display_day(){   
  alt_u8 Tyear, Hyear, Dyear, Nyear;
  Tyear = (alt_u8)(year/1000);
  Hyear = (alt_u8)((year%(1000*Tyear))/100);
  Dyear = (alt_u8)((year%(1000*Tyear+100*Hyear))/10);
  Nyear = (alt_u8)(year%(1000*Tyear+100*Hyear+10*Dyear));
  str1[0]=' ';
  str1[1]=' ';
  str1[2]=' ';
  str1[3]= (alt_u8)(Tyear+0x30);
  str1[4]= (alt_u8)(Hyear+0x30);
  str1[5]= (alt_u8)(Dyear+0x30);
  str1[6]= (alt_u8)(Nyear+0x30);
  str1[7]='-';
  str1[8]=(alt_u8)(month/10+0x30);
  str1[9]=(alt_u8)(month%10+0x30);
  str1[10]='-';
  str1[11]=(alt_u8)(day/10+0x30);
  str1[12]=(alt_u8)(day%10+0x30);
  str1[13]=' ';
  str1[14]=' ';
  str1[15]=' ';
  str1[16]='\0';  
  LCD_Line2();
  LCD_Show_Text(str1);
}

.....

void LCD_Show_Text(char* Text)
{
  int i;
  for(i=0;i<strlen(Text);i++)
  {
    lcd_write_data(LCD_DISPLAY_BASE,Text);
    usleep(2000);
  }
}

这里好像把不同的数都写入了同一个地址??请问是怎么回事?

难道是类似于堆栈的原理?

谢谢!!

请注意lcd_write_cmd()和lcd_write_data()是不同的函数,它们中有语句控制LCD的A0(有的是RS)线,就是这个线决定了是向LCD发指令或是数据。而LCD_DISPLAY_BASE接的应该是LCD的DATA线。

根据你的LCD的初使化命令字看,好像是ST7920的控制器。

以无法为有法,以无限为有限。

 

我的理解是这样:LCD_DISPLAY_BASE在system.h中定义为0x01011080

(#define LCD_DISPLAY_BASE 0x01011080)  0x01011080即在sopc builder中为lcd分配的

基地址(base 0x01011080  end 0x0101108F)

请问这里的base end的地址是什么意思??和哪里对应的??

你说"LCD_DISPLAY_BASE接的应该是LCD的DATA线"是和这里对应吗??我有点不大明白.....

能给我讲一下吗?

谢谢了!

我认为实际上只是LCD_DISPLAY_BASE (0x01011080)该地址所在的一个字节对应着LCD的DATA线,DATA也是8根,一个字节.

从0x01011081开始至0x0101108F都是空着的地址,没有实际的东西与之对应。

以无法为有法,以无限为有限。

哦.....

谢谢了...

在学习NIOS 请求帮助

小弟正在学习NIOS 楼主可否把电子钟的所有原程序发给我 万分感谢

邮箱:djjyt@163.com

楼上的发言对你应该有帮助吧。

你只要掌握了LCD的读写,其它应该不难吧。

真诚让沟通更简单! QQ:767914192
返回列表