首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

真是好難的問題

2012-03-28 
求助 真是好難的問題不知道哪位好心的人可以幫幫我我真的做不出來以下是用AVR做的包含LCDmodule(LCD可顯示

求助 真是好難的問題
不知道哪位好心的人可以幫幫我
我真的做不出來

以下是用AVR做的
包含LCD   module   (LCD   可顯示兩行)   這個部分已經做出來了   一定正確

題目
按A開始計算時間從00:00.0開始   到99:59.9
再按一次A時間會停止   如時間跑到35:11.9時   按A會停在35:11.9再按一次A會從35:11.9   開始(都顯示在第一行)

按B   時間會停止在第二行   但第一行仍然在計時

按D   會把所有時間歸0   就是回到00:00.0的時間

以下是LCD   module   的編程(一定正確的)
這個是LCD_Ddriver.c
#include   <avr/io.h>
#include   <util/delay.h>
#include   "LCD_Driver.h "

//internal   funciton   prototypes
void   LCD_init();
void   LCD_cmd_nibble(char   c);
void   LCD_dat_nibble(char   c);

/*   to   write   the   higer   nibble   of   a   command   to   LCD   module   */
void   LCD_cmd_nibble(char   c)
{
//output   the   higher   nibble   to   LCD   with   RS=0,RD=0,EN=0
LCD_PORT   =   c   &   0xF0;
LCD_PORT   =   LCD_PORT   |   (1 < <EN);
_delay_us(1);//EN=1   for   at   least   .5us
LCD_PORT   =   LCD_PORT   &   (~(1 < <EN));
_delay_us(1);//at   least   1us   for   each   cycle
}

/*   to   write   the   higer   nibble   of   a   data   byte   to   LCD   module   */
void   LCD_dat_nibble(char   c)
{
//output   the   higher   nibble   to   LCD   with   RS=0,RD=0,EN=0
LCD_PORT   =   c   &   0xF0;
LCD_PORT   =   LCD_PORT   |   (1 < <RS);//for   writing   data
LCD_PORT   =   LCD_PORT   |   (1 < <EN);
_delay_us(1);//EN=1   for   at   least   .5us
LCD_PORT   =   LCD_PORT   &   (~(1 < <EN));
_delay_us(1);//at   least   1us   for   each   cycle
}

/*   to   write   a   command   to   LCD   module   */
void   LCD_command(char   cmd)
{
LCD_cmd_nibble(cmd);//higher   nibble
LCD_cmd_nibble(cmd < <4);//lower   nibble
_delay_ms(2);//max   cmd   processing   time:   1.64ms
}

/*   to   display   a   character   in   LCD   module   at   the   current   position*/
void   LCD_display(char   character)
{
LCD_dat_nibble(character);//higher   nibble
LCD_dat_nibble(character < <4);//lower   nibble
_delay_us(50);//max   data   processing   time:   40us
}

/*   to   initialize   the   LCD   module   */
void   LCD_init()
{
_delay_ms(15);

LCD_DDR   =   0xFF;//LCD   port   as   output

        LCD_cmd_nibble(0x30);//set   the   LCD   module   as   8-bit   mode   three   times
_delay_ms(5);
LCD_cmd_nibble(0x30);
_delay_ms(5);
LCD_cmd_nibble(0x30);
_delay_ms(5);

LCD_cmd_nibble(0x20);//set   the   LCD   module   as   4-bit   mode
_delay_ms(5);

//from   now   on   the   LCD   module   works   as   4-bit   mode
//write   cmd   as   normal
LCD_command(0x28);//4-bit   mode,   2-line   dispay,   5x7   dot   char   font


LCD_command(0x08);//display   OFF
LCD_command(0x01);//clear   dispay
LCD_command(0x06);//cursor   increment,   no   shift
LCD_command(0x0F);//dispay   ON   with   cursor   on   and   blinking
}

這個是LCD_Ddriver.h

#ifndef   LCD_DRIVER_H
#define   LCD_DRIVER_H


#define   LCD_PORTPORTB
#define   LCD_DDRDDRB
#define   RS0//pin0
#define   RD1//pin1
#define   EN2//pin2
//pin3:   unused
//pin4-pin7:   4-bit   data   bus  

/******     LCD   funciton   prototypes   *********/
void   LCD_init();//must   be   called   before   the   LCD   module   is   usable
void   LCD_command(char   cmd);//write   a   command   to   LCD   module
void   LCD_display(char   ch);//display   a   character   in   LCD   module
//at   the   current   position   set   by   LCD_command()

#endif


以下就是要做的主程式
我只會把一些字顯示在LCD上   但不會計時
以下就是顯示在LCD上的字的編程
#include   <avr/io.h>
#include   <util/delay.h>

#include   "LCD_Driver.h "

int   main()
{
char   str[]= "Hello,   world! ";
int   i;

//initialize   LCD   module
LCD_init();

//write   character   to   LCD   to   display
LCD_display( 'A ');

//move   cursor   to   2nd   line,   1st   position   and   then   display   characters
LCD_command(0xC0);
i=0;
while(str[i])
{
LCD_display(str[i++]);
}

while(1);
return   0;
}




[解决办法]
计时需要用到AVR片内定时器(我没有用过,你自己去看spec啊)。设置定时器10ms中端一次(100ms也行,随便你)。自己handle定时器中断。伪代码如下:
void timer_isr(void)
{
if (run)
{
++timer_reg;
if (有必要更新显示数据)
刷新LCD显示数据;
}
}

键盘中断处理程序如下:
void key_isr(void)
{
switch (key)
{
case A:
run = !run;
break;
case B:
// do something
break;
case D;
run = 0;
把时间寄存器置零;
break;
}
}

main函数做一下初始化,然后就可以睡大觉了。
[解决办法]
想LCD中输出字符的是这句
LCD_display( '5 ');
首先你获取时间tm
然后分别提取出tm的年月日时分秒,以整数形式保存到如下变量中。
int year,month,day,hour,minute,second;
将整数转换为字符的函数在你的库文件中已提供
ToString(data, data_str);
例如:
char str_year[5];
ToString(year,str_year);
然后依次往设备中输出str_year的字符就可以了
int i=0;
while(1)
{
ch = data_str[i];
if (ch == '\0 ')
{
break;
}
LCD_display(ch);
i++;
}
依次类推,月日时分秒也输出。
如果输出期间发生输出不停止或乱码,甚至内存地址访问出错,注意检查每次将
数字转换为字符后 '\0 '的位置是否准确。
[解决办法]
利用午休时间做的,不太严谨,但应该够你参考了。
首先说一声,如果你的要求不是windows平台的,那就别往下看了,请教高人去吧……
#include <iostream>
using namespace std;
#include <windows.h>
#include <mmsystem.h>
bool time_change_string(DWORD dw,char * szData);
void main()
{
DWORD dwTimeBegin=timeGetTime();//起始时间
DWORD dwCurrentTime=timeGetTime();//当前时间


DWORD dwPauseTime = 0; //中断的时间,既暂停的时间
char strCount[20]= " ";//计时时间字符内容
char strPause[20]= " "; //暂停时间字符内容
BOOL bContinue=TRUE;//表示当前是否处于计时状态
int Key_A_State=0; //状态变量,0表示没有按过A,1表示已经按过A
//该变量影响是否重新计时
BOOL bDown=FALSE;
while(1)
{
system( "cls ");

if(bContinue)
dwCurrentTime=timeGetTime();
else
dwCurrentTime=dwCurrentTime;

//如果按下D,则重置起始时间
if(GetAsyncKeyState( 'D ') & 0x8000)
dwTimeBegin=timeGetTime();
//如果按下B,确定暂停时间字符串
if(GetAsyncKeyState( 'B ') & 0x8000)
time_change_string(dwCurrentTime-dwTimeBegin,strPause);
//如果抬起A,设置状态变量Key_A_State为0
if(!(GetAsyncKeyState( 'A ') & 0x8000))
{
Key_A_State=0;
}
//如果按下A,计时暂停
if(GetAsyncKeyState( 'A ') & 0x8000)
{
if(Key_A_State==0)
{
if(bDown)
{
//如果Key_A_State==1,那么这时按下A表示继续计时
//要让起始时间变为加上暂停的总时间
//例如:12:08:2 时暂停,12:12:5时重新开始计时
//那要让起始时间增加00:04:3才能达到效果
dwTimeBegin += (timeGetTime()-dwPauseTime);
bContinue=TRUE;
bDown=FALSE;
}
else
{
bContinue=FALSE;
dwPauseTime = dwCurrentTime;
bDown=TRUE;
}
}
Key_A_State=1;
}
time_change_string(dwCurrentTime-dwTimeBegin,strCount);
cout < <strCount < <endl;
cout < <strPause < <endl;
}
system( "pause ");
}

bool time_change_string(DWORD dw,char * szData)
{
//szData的总长度没做过多检测,请传递实参时确认一下其字符长度大于等于8个字符
if(!szData)
return false;
int count_seconds=dw/1000;//总秒数
int count_minutes=count_seconds/60;//总分数

//*************确定分钟字符内容*******************//
if(count_minutes==0)
{
//如果一分钟都没有,确定分钟的字符 "00 "
szData[0]=szData[1]= '0 ';
}
else
{
if(count_minutes <10)
{
//小于10分
szData[0]= '0 ';
wsprintf(szData+1, "%d ",count_minutes);
}
else
{
wsprintf(szData, "%d ",count_minutes);
}
}
szData[2]= ': ';
//***************分钟结束*********************//


//*************确定秒字符内容*******************//
count_seconds%=60;//总秒数变为去掉分钟后的剩余秒数
if(count_seconds==0)
{
//如果是整分,确定秒的字符 "00 "
szData[3]=szData[4]= '0 ';
}
else
{
if(count_seconds <10)
{
//小于10秒
szData[3]= '0 ';
wsprintf(szData+4, "%d ",count_seconds);
}
else
{
wsprintf(szData+3, "%d ",count_seconds);
}
}
szData[5]= ': ';
//***********************秒结束*****************//

//********************十分之一秒***************//
dw%=1000; //dw变为去掉所有秒以后的滴答计数
int count_milseconds = dw/100; //十分之一秒总数,保证只有1位数字
wsprintf(szData+6, "%d ",count_milseconds);
szData[8]= '\0 ';
//********************十分之一秒结束***********//
}


bool time_change_string(DWORD dw,char * szData)是我自己做的将滴答计数转换为字符的函数
其实你完全可以把内部代码换成ToString,你自己的库方法。

timeGetTime()是获取从你的计算机开机后到当前的总滴答计数,大约每秒为1000次。
也就是说,第二次调用该函数得到的返回值减去第一次调用的返回值,就是2次间隔的滴答数之差。
但该函数要求包含#include <mmsystem.h> ,而且你的项目属性里要包含附加依赖项winmm.lib。
返回值为DWORD,所以包含一下 <windows.h>

热点排行