📄 main._c
字号:
while((0xf0&PINA)!=0xf0);
break;
}
}
keycode=0xff;
}
switch(keycode)
{
case 0x00:return '1';
case 0x01:return '2';
case 0x02:return '3';
case 0x03:return 'a';
case 0x04:return '4';
case 0x05:return '5';
case 0x06:return '6';
case 0x07:return 'b';
case 0x08:return '7';
case 0x09:return '8';
case 0x0a:return '9';
case 0x0b:return 'c';
case 0x0c:return '*';
case 0x0d:return '0';
case 0x0e:return '#';
case 0x0f:return 'd';
case 0xff:return 0xff;
default:return 0xff;
}
}
unsigned char bitchg(unsigned char bit)//四位bit码翻译成行列位置
{if(bit&0x01) bit=0;
else if(bit&0x02) bit=1;
else if(bit&0x04) bit=2;
else bit=3;
return(bit);
}
int scannum(void)//键盘输入一整型数据
{
unsigned char strnum[6];
unsigned char i;
int keynum=0;
keyflag=1;
for(i=6;i>=0;i--)
{
do{keycode=key_scanonce();}while(keycode==0xff);//一直扫描键盘,到有按键按下
if(keycode=='d') //是否回车(d号键) ?是 !
{
delay_nms(10);display_a_char((26-i),0x7f);
if(strnum[0]=='b')//负数的运算
{switch(i)
{
case 5:keynum=0;break;
case 4:keynum=(-1)*(strnum[1]);break;
case 3:keynum=(-1)*(strnum[1]*10+strnum[2]);break;
case 2:keynum=(-1)*(strnum[1]*100+strnum[2]*10+strnum[3]);break;
case 1:keynum=(-1)*(strnum[1]*1000+strnum[2]*100+strnum[3]*10+strnum[4]);break;
case 0:keynum=(-1)*(strnum[1]*10000+strnum[2]*1000+strnum[3]*100+strnum[4]*10+strnum[5]);break;//|keynum|应小于32767
}
}
else //正数的运算
{switch(i)
{
case 6:keynum=0;break;
case 5:keynum=strnum[0];break;
case 4:keynum=strnum[0]*10+strnum[1];break;
case 3:keynum=strnum[0]*100+strnum[1]*10+strnum[2];break;
case 2:keynum=strnum[0]*1000+strnum[1]*100+strnum[2]*10+strnum[3];break;
case 1:keynum=strnum[0]*10000+strnum[1]*1000+strnum[2]*100+strnum[3]*10+strnum[4];break;//keynum应小于32767
}
}
break;//直接从if中跳出for循环
}
else //是否回车(d号键) ?否 !
{
if(keycode=='c') //是否清除(c号键) ?是 !
{delay_nms(10);display_a_char((25-i),' ');i+=2;}
else //是否清除(c号键) ?否 !
{
if(keycode=='b') //是否负号(b号键) ?是 !
{delay_nms(10);display_a_char((25-i),'-');strnum[6-i]=keycode-0x30;}
else //是否负号(c号键) ?否 !
{delay_nms(9);display_a_char((26-i),keycode);strnum[6-i]=keycode-0x30;}
}
}
}
keyflag=0;
return(keynum);
}
/*====================================液晶驱动函数============================*/
//液晶初始化
void lcd_init(void)
{
delay_nms(30);
lcd_data_port=0xff;
lcd_data_ddr=0xff;
lcd_control_port=0x00;
lcd_control_ddr=0x07;
lcd_write_command(0x38,0);//显示模式设置一次(此时不管lcd空闲与否)
lcd_write_command(0x38,1);//显示模式设置(从此之后均需lcd空闲)
lcd_write_command(0x08,1);//显示关闭
lcd_write_command(0x01,1);//显示清屏
lcd_write_command(0x06,1);//显示光标移动设置
lcd_write_command(0x0c,1);//显示开及光标设置
delay_nus(30);
lcd_write_command(0x01,1);//显示清屏
}
//写指令函数: E="高脉冲" RS="0" RW="0" command为指令,wait_en指定是否要判忙
void lcd_write_command(unsigned char command,unsigned char wait_en)
{
if(wait_en)wait_enable();//若wait_en为1,则要检测LCD忙信号,等待其空闲
lcd_control_port&=~lcd_RS;//RS=0
lcd_control_port&=~lcd_RW;//RW=0
lcd_control_port&=~lcd_EN;//E=0,下面给LCD一个高脉冲
lcd_data_ddr=0xff;
lcd_data_port=command;
lcd_control_port|=lcd_EN;//E=1
lcd_data_port=command;
lcd_control_port&=~lcd_EN;//重设E=0
}
//写数据函数: E =高脉冲 RS="1" RW="0"
void lcd_write_data(unsigned char char_data)
{
wait_enable();//等待LCD空闲
lcd_control_port|=lcd_RS;//RS=1数据
lcd_control_port&=~lcd_RW;//RW=0写
lcd_control_port&=~lcd_EN;//E=0,下面给LCD一个高脉冲
lcd_data_ddr=0xff;
lcd_data_port=char_data;
lcd_control_port|=lcd_EN;//E=1
lcd_data_port=char_data;
lcd_control_port&=~lcd_EN;//重设E=0
}
//正常读写操作之前必须检测LCD控制器状态:E=1 RS="0" RW="1";DB7: 0 空闲,1 忙。
//检测忙信号,等待LCD空闲函数
void wait_enable(void)
{
lcd_busy_ddr&=~busy;//设置busy口为输入
lcd_control_port&=~lcd_RS;//RS=0
lcd_control_port|=lcd_RW;//RW=1
lcd_control_port&=~lcd_EN;//E=0,下面给LCD一个高脉冲
NOP();
lcd_control_port|=lcd_EN;//E=1
while(lcd_busy_pin&busy);//等待LCD_DB7为0
lcd_control_port&=~lcd_EN;//重设E=0
lcd_busy_ddr|=busy;//设置busy口为输出
}
void display_a_char(unsigned char position,unsigned char char_data)//参数position指定位置0~79,char_data为要显示的字符
{
unsigned char position_tem;
if(position<20) //第一行时,地址为0x80到0x93,输入的数值加上0x80, 就是当前的地址值;
position_tem=position+0x80;
else if(position<40)//第二行的地址为0xc0到0xd3,当为第二行时position>20,此时地址值应为position+0xc0-0x20即position+0xac;
position_tem=position+0xac;
else if(position<60)//第三行的地址为0x94到0xa7,当为第三行时position>40,此时地址值应为position+0x94-0x40即position+0x6c;
position_tem=position+0x6c;
else//第四行的地址为0xd4到0xe7,当为第三行时position>60,此时地址值应为position+0xd4-0x60即position+0x98;
position_tem=position+0x98;
lcd_write_command(position_tem,1);
lcd_write_data(char_data);
}
//指定位置显示任意大小字符串,psition:位置,prt:要显示的字符串
void display_a_string(unsigned char position,unsigned char *ptr)
{
while(*ptr++!='\0')display_a_char(position++,*ptr);//位置++字符串指针++
}
//指定位置显示一个整数,psition:位置,num:要显示的整数(新写,未测试)
void display_a_number(unsigned char position,int num)
{
unsigned char i,flag=0;//flag判断是否出现了有效位
if(num<0)//是负数则显示'-'然后转为正数显示
{display_a_char(position++,'-');num*=-1;}
for(i=4;i>=0;i--)//依次整除1000,1000,100,10,1得到字符并显示
{
if(num/nten(i))//非0位,要显示,并把flag置1
{
flag=1;
display_a_char(position++,num/nten(i));
num=num%nten(i);
}
else//0位
{
if(flag)display_a_char(position++,'0');//是0位并且是有效位,显示'0'
}
}
}
//void display_a_number(unsigned char position,int num)
// {
// int j;
// unsigned char i,x;
// if(num>=10000)i=5;
// else if(num<10000&&num>=1000)i=4;
// else if(num<1000&&num>=100)i=3;
// else if(num<100&&num>=10)i=2;
// else if(num<10&&num>=0)i=1;
// else if(num<=-10000)i=15;
// else if(num>-10000&&num<=-1000)i=14;
// else if(num>-1000&&num<=-100)i=13;
// else if(num>-100&&num<=-10)i=12;
// else i=11;
// if(i<10)
// {for(;i>0;i--)
// {
// j=nten(i-1);
// x=num/j;
// display_a_char(position,x+0x30);
// num=num%j;
// position++;
// }
// }
// else
// {
// i-=10;
// display_a_char(position,'-');
// position++;
// for(;i>0;i--)
// {
// j=nten(i);
// x=num/j;
// display_a_char(position,x+0x30);
// num=num%j;
// position++;
// }
// }
// }
//10的n次方转换
int nten(unsigned char n)
{int m=1;
for(;n>0;n--)
{m*=10;}
return(m);
}
/*====================================计时函数================================*/
void time_init(void)
{
SREG=0x80;
TIMSK=0x02;
TCCR0=0x04; //T/C0工作于定时方式,系统时钟256分频
TCNT0=0x06; //计数初始值6
}
/*====================================延时函数================================*/
void delay_ns(unsigned int n)
{
unsigned int i,j;
for(i=0;i<n;i++)
{for(j=1000;j>0;j--)delay_1ms();
}
}
//n ms延时函数
void delay_nms(unsigned int n)
{
unsigned int i;
n-=n/1000;
for(;n!=0;n--){for(i=1328;i!=0;i--) ; }
}
//1ms延时函数
void delay_1ms(void)
{
unsigned int i;
for(i=1328;i!=0;i--);
}
//n us延时函数
void delay_nus(int n)
{while(n--);}
/*===================================端口初始化===============================*/
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = 0x00;
DDRB = 0x00;
PORTC = 0x00;
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x00;
PORTE = 0x00;
DDRE = 0x00;
}
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
lcd_init();
wgm_init();
time_init();
MCUCR = 0x00;
EMCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x00;
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
/*==============================T/C0中断服务函数==============================*/
//声明中断名及中断向量号
#pragma interrupt_handler Timer0:8
void Timer0(void)
{
num++; //中断次数累加
if(num==122)
{
num=0; //计数到125次,计数值复位,125为理论值,122为试验值
second++; //秒加1
if(second==60)
{second=0;
minute++;} //分进位
if(keyflag==0)//显示屏右下角显示系统时间mm:ss
{if(minute<10){display_a_char(75,'0');display_a_number(76,minute);}
else display_a_number(75,minute);
display_a_char(77,':');//分秒之间显示':'
if(second<10){display_a_char(78,'0');display_a_number(79,second);}
else display_a_number(78,second);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -