📄 main.c
字号:
/********************************************************************
* 主 页 : HTTP://WWW.QLMCU.COM
*
* 程序功能 : 时钟演示程序、蜂鸣器、发光二极管测试
*
* 应用软件 : WinAVR
*
* 版 本 : WinAVR-20050214-install
*
* 硬 件 : WS9500、WS9600 (工作频率: 6MHz)
*
* 创建时间 : 2005-11-10
*
* 编 写: benladn911
*
* 注:为了有更多实用的实验程序供大家学习,部分程序参考网上的资源,
* 在此谢谢这些无私奉献的朋友!!!
*
********************************************************************/
#include"avr/io.h" //头文件
#include <avr/delay.h> //延时函数
#include"avr/interrupt.h" //中断处理函数
#include"avr/signal.h" //中断处理函数
#define uchar unsigned char
#define uint unsigned int
//内部函数_delay_ms() 最高延时 262.144mS@1MHz 即 32.768ms@8MHz
void delay_ms(unsigned int ms);//----ms级延时
//内部函数_delay_us() 最高延时 768 us@1MHz 即 96 us@8MHz
void delay_us(unsigned int us);//----us级延时
void BEEP(void);//----蜂鸣器子程序
//-----------位操作定义------------------------
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define BEEP_ON cbi(PORTD,2)//在程序用BEEP_ON代替cbi(PORTD,2)
#define BEEP_OFF sbi(PORTD,2)//在程序用BEEP_OFF代替sbi(PORTD,2)
#define LED_ON cbi(PORTD,7)//在程序用LED_ON代替cbi(PORTD,7)
#define LED_OFF sbi(PORTD,7)//在程序用BEEP_ON代替sbi(PORTD,7)
//数码管字型表,对应0,1,2,3,4,5,6,7,8,9//
uchar Table[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0xff};
uchar Data[6]={0,0,0,0,0,0}; //显示初始值:0 0 0 0 0 0
uchar CNT=0; //初始计数值:0
uchar Timer[3]={0x00,0x00,0x00}; //初始时间00:00:00
//--------------------------------------------------------------------------
//定义MCU与LCD的接口
#define LCD_RS_PORT PORTC
#define LCD_EN_PORT PORTC
#define LCD_RW_PORT PORTC
#define LCD_DATA_PORT PORTA
#define LCD_DATA_DDR DDRA
#define LCD_DATA_PIN PINA
#define LCD_RS (1<<5) //PORTC5 out
#define LCD_EN (1<<7) //PORTC7 out
#define LCD_RW (1<<6) //PORTC6 out/in
#define LCD_DATA 0xf0 //PORTA4/5/6/7 out
//-------函数声明------------------------------------------------------------
void LCD_init (void);
void LCD_en_write (void);
void LCD_write_char (unsigned command,unsigned data);
void LCD_wait_Ready (void);
void LCD_set_xy (unsigned char x, unsigned char y);
void LCD_write_string (unsigned char X,unsigned char Y,unsigned char *s);
//--------------------------------------------------------------------------
/*----------------------------------------------------
光标命令
LCD_write_char(0x0e,0); //光标开
LCD_write_char(0x0d,0); //光标所在字符闪烁
LCD_write_char(0x0c,0); //光标关
-------------------------------------------------------*/
//----------------ms级延时---------------
void delay_ms(unsigned int ms)
{
unsigned int i;
for(i=0;i<ms;i++) _delay_ms(1); //延时 i*ms= 毫秒,可自行调节
}
//----------------us级延时---------------
void delay_us(unsigned int us)
{
unsigned int i;
for(i=0;i<us;i++) _delay_us(1); //延时 i*us= 毫秒,可自行调节
}
//-------------------- 数码管动态扫描程序------------------------
void Display(uchar *p) //动态显示函数,参数p为待显示的数组名
{
//-----------------第一种动态扫描方式-----------------
uchar i,sel=0b11111110;
for(i=0;i<6;i++)
{
PORTB=sel; //选通最右边的数码管
PORTA=Table[p[ i ]]; //送字型码
delay_ms(2); //显示延时
sel=(sel<<1)|0b00000001; //移位以显示前一位
}
/*//-------------第二种动态扫描方式-----------------
uchar i=0,sel=0b11111110;
PORTB=sel;
PORTA=Table[p[ i ]]; //送字型码
delay_ms(2); //显示延时
i++;
sel=0b11111101;
PORTB=sel;
PORTA=Table[p[ i ]]; //送字型码
delay_ms(2); //显示延时
i++;
sel=0b11111011;
PORTB=sel;
PORTA=Table[p[ i ]]; //送字型码
delay_ms(2); //显示延时
i++;
sel=0b11110111;
PORTB=sel;
PORTA=Table[p[ i ]]; //送字型码
delay_ms(2); //显示延时
i++;
sel=0b11101111;
PORTB=sel;
PORTA=Table[p[ i ]]; //送字型码
delay_ms(2); //显示延时
i++;
sel=0b11011111;
PORTB=sel;
PORTA=Table[p[ i ]]; //送字型码
delay_ms(2); //显示延时
*/
}
//计数值处理函数。参数p1:时间数组名;参数p2:显示数组名//
//功能:此函数用于将计数值拆分为BCD码的10时,时,10分,分,10秒,秒//
void Process(uchar *p1,uchar *p2)
{
p2[0]=p1[0]/10;
p2[1]=p1[0]-p2[0]*10;
p2[2]=p1[1]/10;
p2[3]=p1[1]-p2[2]*10;
p2[4]=p1[2]/10;
p2[5]=p1[2]-p2[4]*10;
}
//--------------初始化I/O口------------------
void Init_IO(void) //初始化I/O口
{
PORTA=0xff;
DDRA=0xff; //设置A口为推挽1输出
PORTB=0xff; //PORTC=0xff;
DDRB=0xff; //DDRC=0xff; //设置C口为推挽1输出;
}
//-------------------主程序--------------------
int main(void)
{
delay_ms(1000);
DDRA |= LCD_DATA ;//
//DDRC = 0XFF;
DDRC |= LCD_RS | LCD_EN | LCD_RW ; //
LCD_init();//初始化
delay_ms(200);
LCD_write_char(0x01,0); //显示清屏
delay_ms(500);
LCD_write_string(1,0,"WWW.QLMCU.COM");
delay_ms(200);
LCD_write_string(1,1,"0595-22313231");
delay_ms(1000);
Init_IO();//初始化I/O口
PORTA=0X00;//测试发光二极管
sbi(DDRD,7);
LED_ON;
BEEP();//测试蜂鸣器
delay_ms(500);
BEEP();
delay_ms(500);
BEEP();
delay_ms(2000);//延时
PORTB=0xff; //熄灭所有的数码管
LED_OFF;//关闭发光二极管
PORTA=0XFF;
TCCR0=0x04;//T/C0工作于定时方式,系统时钟256分频
TCNT0=0x06;//计数初始值6
TIMSK=0x02;//开放TOV0中断
SREG=SREG|0x80;//开放总中断
while(1)
{
Process(Timer,Data); //计数值处理
Display(Data); //动态扫描显示
}
}
//---------------------T/C0中断服务函数-------------------------
SIGNAL(SIG_OVERFLOW0)
{
TCNT0=0x06; //重装计数初始值6
CNT++; //中断次数累加
if(CNT==125)
{CNT=0; //计数到125次,计数值复位
Timer[2]++; //秒加1
if(Timer[2]==60)
{Timer[2]=0;
Timer[1]++;
} //分进位
if(Timer[1]==60)
{Timer[1]=0;
Timer[0]++;
} //时进位
if(Timer[0]==24)
{Timer[0]=0;
}
} //计数到达最高位,计数复位
}
//---------------蜂鸣器子程序-------------
void BEEP(void)
{
unsigned int j;
sbi(DDRD,2);//把PB2设置为输出(蜂鸣器)
for(j=200;j>0;j--)
{
BEEP_ON;delay_us(500);
BEEP_OFF;delay_us(40);//2.5KHz
}
delay_us(10);
for(j=200;j>0;j--)
{
BEEP_ON;delay_us(600);
BEEP_OFF;delay_us(40);//1.25KHz
}
delay_us(5);
for(j=200;j>0;j--)
{
BEEP_ON;delay_us(600);
BEEP_OFF;delay_us(40);//1.25KHz
}
}
/*---------------LCD初始化----------------*/
void LCD_init(void)
{
delay_ms(50); //*************
LCD_write_char(0x30,0);
delay_ms(6);
LCD_write_char(0x30,0); //这段加上去,不用阿莫介绍延时的那种
delay_ms(1);
LCD_write_char(0x30,0);
delay_ms(1);
LCD_write_char(0x02,0); //*******************/
delay_ms(1);
LCD_write_char(0x28,0); //4bit test 显示模式设置(不检测忙信号)
delay_ms(1);
LCD_write_char( 0x08, 0); // 显示关闭
delay_ms(1);
LCD_write_char( 0x01, 0); // 显示清屏
delay_ms(1);
LCD_write_char( 0x06, 0); // 显示光标移动设置
delay_ms(1);
LCD_write_char( 0x0C, 0); // 显示开及光标设置
delay_ms(10);
}
/*---------------写入使能---------------*/
void LCD_en_write(void) //EN端产生一个高电平脉冲,写LCD
{
LCD_EN_PORT |= LCD_EN;
delay_us(20);
LCD_EN_PORT &= ~LCD_EN;
delay_us(20);
}
/*-----------------------------------------------------------------------
LCD_write_char : 英文字符串显示函数
输入参数:*s :英文字符串指针;
X、Y : 显示字符串的位置,X:0-15,Y:0-1
LCD第一行显示寄存器地址:0X80-0X8F
LCD第一行显示寄存器地址:0XC0-0XCF
编写日期 :2005-10-7
最后修改日期 :
-----------------------------------------------------------------------*/
void LCD_write_char(unsigned command,unsigned data)
{
unsigned command_temp,data_temp;
command_temp = command;
data_temp = data;
LCD_wait_Ready();
LCD_RW_PORT &= ~LCD_RW; //RW=0
LCD_DATA_PORT &= 0X0f;
if (command == 0)
{
LCD_RS_PORT |= LCD_RS; //RS=1
LCD_DATA_PORT |= data_temp&0xf0; //send high 4bit
}
else
{
LCD_RS_PORT &= ~LCD_RS; //RS=0
LCD_DATA_PORT |= command_temp&0xf0;//send high 4bit
}
LCD_en_write();
LCD_DATA_PORT &= 0X0f;
command_temp=command_temp << 4; //send low 4bit
data_temp=data_temp << 4;
if (command==0)
LCD_DATA_PORT |= data_temp&0xf0;
else
LCD_DATA_PORT |= command_temp&0xf0;
LCD_en_write();
LCD_RW_PORT |= LCD_RW;
LCD_RS_PORT ^= LCD_RS;
}
void LCD_wait_Ready(void) //等待LCD空闲
{
LCD_DATA_DDR &= ~0x80; //PD7 I/O口方向设置为输入
LCD_RW_PORT |= LCD_RW; //RW=1
LCD_RS_PORT &= ~LCD_RS; //RS=0
LCD_EN_PORT |= LCD_EN; //EN=1
while (!( LCD_DATA_PIN&0x80 ) == 0); //RW=1,读PD7,为0表示空闲;
LCD_EN_PORT &= ~LCD_EN; //EN=0
LCD_DATA_DDR |= 0xf0;
}
/*-----------------------------------------------------------------------
LCD_set_xy : 设置LCD显示的起始位置
输入参数:x、y : 显示字符串的位置,X:0-15,Y:0-1
LCD第一行显示寄存器地址:0X80-0X8F
LCD第一行显示寄存器地址:0XC0-0XCF
编写日期 :2005-10-7
最后修改日期 :
-----------------------------------------------------------------------*/
void LCD_set_xy( unsigned char x, unsigned char y )
{
unsigned char address;
if (y == 0) address = 0x80 + x;
else
address = 0xc0 + x;
LCD_write_char( address, 0 );
}
/*-----------------------------------------------------------------------
LCD_write_string : 英文字符串显示函数
输入参数:*s :英文字符串指针;
X、Y : 显示字符串的位置
编写日期 :2005-10-7
最后修改日期 :
-----------------------------------------------------------------------*/
void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s)
{
LCD_set_xy( X, Y );
while (*s)
{
LCD_write_char( 0, *s );
s ++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -