📄 homework1.1.c
字号:
/*****************************Copyright(c)***************************
***************************File Info********************************
** File name: homework.c
** Created by: 邵峰sshaofeng@163.com
** Descriptions: 电动机智能控制(两个按键,一开启键二强制中断键,双LED数码管显示)
** function: 第一台运转5s后停止,切换到第二台运转,10s后第二台自动停止。
** Date: 2008-6-30
*******************************************************************/
/***************************版本更新说明************************
控制电动机智能启动,按启动键后,第一个电动机运行5秒后停止,自动转向运行第二个电动机,
十秒后,它也停止。
显示是用两位数码管动态显示,电动机用LED灯来表示。
homework.c :用50次20ms的for循环来实现1s的间隔,按下瞬间有效;
homework1.0.c:用50次20ms的for循环来实现1s的间隔,抬起瞬间有效,但在按下的时候;程序(现象)停滞;
homework1.1.c:用50次20ms的for循环来实现1s的间隔,抬起瞬间有效,解决上述问题;
****************************************************************/
#include <mega16.h> //Atmel16的头文件
#include <delay.h> //CVAVR的特色delay function.
int i,kk=0; //定义变量类型及赋初值
const char dig0 = 0x40, dig1 = 0x80, dig2=0x10, dig3=0x08, dot=0x20; //定义静态变量
char segconv[]={0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};//共阴极表,但本实验板为共阳极的。
unsigned char BCD0, BCD1;
interrupt [EXT_INT0] void ext_int0_isr(void) //外中断0服务程序
{
GICR&=~0X40; //禁止外中断0中断
while(PIND.2==0); // INT0本身就是用PD.2口控制,无此条语句仍可完成
// delay_ms(30); //while(PIND.2==0); 的作用是等待PD2的按键抬起,即抬起后之后程序有效,
PORTA=0X00; //若无while(PIND.2==0);语句,中断服务程序从PD.2口按下时便开始执行。
// PORTB=0X00; //本实验板PB口为LED的段选,而PA后四位为LED的位选,同时控制电机,则上条指令已达到关断作用
kk=1; //引入变量kk,并使其置一
GICR|=0X40; //允许外中断0中断
GIFR=0X40; //清除标志位
}
void port_init(void) // the initialization function
{
PORTA = 0x00; //设全为低
DDRA = 0xFF; //设置为输出
PORTB = 0xFF; //设全为高
DDRB = 0xFF; //设置为输出
PORTC = 0xFF; //set the default
DDRC = 0x00; //C口设置为输入
PORTD = 0x00; //设全为高
DDRD = 0xFB; //PD.2和PD.4设置为输入,其余设置为输出,
} //因为PD.2口为INT0的控制位
//*****************************************************************
void BinToBCD(int data) //十进制函数
{
BCD0=0; //BCD0、1、2、3分别为个十百千位
BCD1=0; //设初值
if(data>=10)
{
BCD1=data/10; //商给十位
data=data%10; //余给个位
}
BCD0=data;
}
void dispseg(void)
{
PORTB=~segconv[BCD0]; //本实验板为共阳极,而表为共阴极的表,故用~符号取反后,再送值。
PORTA=dig0; //送数(打开该LED位选,高电平有效)
delay_ms(10); //延时10ms
PORTB=~segconv[BCD1]; //写数
PORTA=dig1; //送数(打开该LED)
delay_ms(10); //延时10ms
}
void display(int data) //集成显示子程序,
{
BinToBCD(data); //一次定义和运行即可,现在的编写则是每次都需运行,不好。
//说得不对,display()为void函数,而数值与data有关,他每次必用。
dispseg();
}
void run(void) //执行子函数
{
char j;
PORTD.6=1; //PD.6控制第一台电机,PA.6控制对应的LED(即最右边的led)
PORTA.6=1; //The first motor operates,meanwhile, this bit control a LED Digitron (LED数码管)
kk=0; //对变量kk设初值,kk的引入解决了在5秒和10秒for循环过程中输入无效的问题
for(i=1;i<6;i++) //display five seconds
{
for(j=0;j<50;j++)
{
display(i); //本身运行20ms,运行50次,则共1s。
if(kk==1)
break; //判断后,用break直接跳出,否则之后几秒循环时间内,按启动键无效
} //break是结束整个循环
//kk在中断服务程序中被赋值,当中断启动后kk=1
}
PORTD.6=0;
if(kk==0) //当kk仍=0时,向下运行,INT0服务程序中有"kk=1"的语句,即当按下
{ //按INT0键后,不再执行下面程序。
PORTD.7 = 1;
PORTA.7 = 1; //The second motor operates,meanwhile, this bit control a LED Digitron (LED数码管)
for(i=1;i<11;i++) //display ten seconds
{
for(j=0;j<50;j++)
{
display(i);
if(kk==1)break; //判断后,用break直接跳出,否则之后几秒循环时间内,按启动键无效
}
}
PORTD.7=0;
PORTA.7=0; //The second motor stops. and if it hasn't this instruction,the led and digitron will light all the time
// I think the reason may be it has a buffer.
}
}
void main(void) //主函数
{
port_init(); // call intialization
GICR|=0x40; //使能外中断0
MCUCR=0x02; //INT0下降沿产生中断请求
MCUCSR=0x00;
GIFR=0x40; //清除外中断0标志位
#asm("sei") //使能总中断
while(1) //无条件循环
{
if(PINC.1==0) //判断启动键是否按下
{
delay_ms(10); //延时去抖动
if(PINC.1==0) //确认该键是否按下
run(); // call run()
PORTA.7=0; //清除残存显示
}
// display(i); //目的:数码管始终在显示,而不是原先按下才开始显示。
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -