整个程序看着比较麻烦,给你一个思路吧,这是我以前做的一个单片机测电机转速的大概流程:
首先需要一个定时器和计数器,定时器1设置1S定时溢出中断,定时器2设置8个脉冲计数溢出中断(当时的项目是8个脉冲为一圈)。如果计数中断先执行,那么当前已定时的时间就是转1圈需要的时间,然后计算转速并更新显示,然后再初始化定时器和计数器。如果定时中断先执行,那么就获取当前的脉冲数来计算转速,以及更新显示,然后再初始化定时器和计数器。这样最多1S以后,如果转速为零,那么显示也会归零
可能有2点原因:
1 中断服务中switch语句中没有break语句, 导致PORTA=0X0F;接着设定了PORTA=0XF0; 可能case 1时会出现闪或看不到效果
2 中断产生了重入 导致中断服务再次打断,后果无法预知,建议修改如下(含第1点)
#pragma interrupt_handler int0_isr:iv_INT0
void int0_isr(void)
{
//external interupt on INT0
//stop errant interrupts
CLI(); //disable all interrupts
i++;
switch(i%2)
{
case 1:PORTA=0X0F;break;
case 0:PORTA=0XF0;break;
}
SEI(); //re-enable interrupts
Delay_ms(200);
}
另外还有1点最好检查下: 在中断中使用Delay_ms好用么
补充:
因为在中断中延时函数是无效的建议你修改下整个代码的机制:
中断中设定全局变量或发送消息,并禁止中断,在main()判断全局变量或接收消息,判断中断产生后设定PORTA,并延时200ms,延时时间到后再中断使能
volatile BOOL intr_flag = FALSE;
void int0_isr(void)
{
//external interupt on INT0
//stop errant interrupts
CLI(); //disable all interrupts
intr_flag = TRUE;
}
void main(void)
{
init_devices();
while(1)
{
if (intr_flag == TRUE) {
i++;
switch(i%2)
{
case 1:PORTA=0X0F;break;
case 0:PORTA=0XF0;break;
}
Delay_ms(200);
intr_flag = FALSE;
SEI(); //re-enable interrupts
}
}
}
//绝对调试通过,AVR-GCC,mega16,带数码显示,单键开关多功能控制
#include <avr/ioh>
#include <avr/interrupth>
#include <toneh>
#include <avr/pgmspaceh>
#define uchar unsigned char
#define uint unsigned int
#define key_input PINA
#define pgm16(A) ((typeof(A))pgm_read_word(&(A)))
const unsigned char seg_code[] ={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0x7f,0x3f};
const uint music[] PROGMEM={M3,F2,M5,B1,M3,F4,M2,F4,M1,B2,L6,F2,M1,F2,MM,M1,F2,L6,F2,L5,B2, L6,F2,M1,B1,MM,M1,F2,L6,F2,M6,F2,L5,F2,M3,F2,M2,F2,MM,M2,F4,M1,F4,L6,F2,M3,F2,M2,B2,
M3,F2,MM,M3,F2,MM,M3,F2,M2,F2,M1,B2,L6,F2,M1,F2,L7,F2,L5,F2,L6,B2, L5,F2,L6,F2,MM,L6,F2,L5,F2,M6,F2,M5,F2,MM,M5,F2,M3,F2,M2,F2,MM,M2,F4,M3,F4,M3,F2,M2,F2,M1,B2,
M6,F2,H1,B1,M6,F2,H2,F2,H1,F2,MM,H1,F2,M6,F2,MM,M6,F2,M5,F2,MM,M5,F2,M3,F2,M5,B2, M6,F2,H1,B1,M6,F2,H2,F2,H1,F2,MM,H1,F2,M6,F2,M5,F2,MM,M5,F2,MM,M5,F2,M3,F2,M2,B2,
M3,B1,MM,M3,F2,M5,F2,M6,F2,M5,F2,MM,M5,F2,M3,F2,MM,M3,F2,M2,F2,MM,M2,F2,M1,F2,L6,B2, L5,F2,M5,F4,MM,M5,F4,MM,M5,F2,M6,F2,M5,F2,M3,F2,M2,F2,M3,F2,MM,M3,F2,M2,B1,L6,F2,M1,B2,
M6,F2,H1,B1,M6,F2,H2,F2,H1,B1,M6,F2,MM,M6,F2,M5,F2,MM,M5,F2,M3,F2,M5,B2, M6,F2,H1,B1,M6,F2,H2,F2,H1,B1,M6,F2,
M5,F2,MM,M5,F2,MM,M5,F2,M3,F2,M2,B2,MM, M2,F2,MM,M2,F4,M1,F4,M2,F2,M3,F2,M5,F2,MM,M5,F2,MM,M5,F2,M3,F2,M2,F2,MM,M2,F4,M3,F4,M2,F2,M1,F2,L6,B2,
L5,F2,M5,F4,MM,M4,F4,MM,M5,F2,M6,F2,M5,F2,M3,F2,M2,F2,M2,F4,M3,F4,MM,M3,F2,M2,B1,L6,F2,M1,B3,0XFF,0XFF};
//因为两个相同的音符之间无停顿,人为插入了MM(极短暂的
volatile uint i=1;
volatile uchar timeOK=0;
uchar key_scan(void);
ISR(TIMER0_COMP_vect) //CTC模式,控制音调高低
{
OCR0=pgm16(music[i-1]);
}
ISR(TIMER1_OVF_vect) //时间溢出模式,控制节拍长短
{
i+=2;
TCNT1H=(65536-pgm16(music[i]))/256; //相当于(65536-beat[i])/256
TCNT1L=(65536-pgm16(music[i]))%256; //相当于(65536-beat[i])%256
if(pgm16(music[i])==0xff)i=1; //在音调数组的最后加一个0xff,作为终止信号
if(pgm16(music[i])==0x00)TIMSK&=(~(1<<OCIE0));
else TIMSK|=(1<<OCIE0);
}
ISR(TIMER2_OVF_vect) //时间溢出模式,用于检测按键,周期10ms
{
TCNT2=100;
timeOK=1;
}
void timer0_init(void)
{
TCCR0=0x00;
TCNT0=0x00;
OCR0=pgm16(music[i-1]);
TCCR0=0x1a;
//TIMSK|=(1<<OCIE0);
}
void timer1_init(void)
{
TCCR1B=0x00;
TCNT1H=(65536-pgm16(music[i]))/256;
TCNT1L=(65536-pgm16(music[i]))%256;
TCCR1A=0x00;
TCCR1B=0x05;
//TIMSK|=(1<<TOIE1);
}
void timer2_init(void)
{
TCCR2=0x00;
TCNT2=100;
TCCR2=0x03;
TIMSK|=(1<<TOIE2);
}
void MCU_init(void)
{
DDRA=0X00;
DDRB=0X00;
DDRC=0XFF;
DDRD=0XFF;
PORTB=0X00;
PORTC=0xfe;
PORTD=0xff;
}
uchar key_scan(void) //按钮扫描函数
{
static uchar key_state=0,key_time1=0,key_time0=0; //静态变量,调用以后,值被保留;
uchar key_press,key_return=0;
key_press=(~key_input)&0x01; //有键1,无键0
switch(key_state) //状态机
{
case 0: //状态0:无按钮按下状态
if(key_press)key_state=1;
break;
case 1: //状态1:检测到有按钮被按下
if(key_press) //按钮仍按下,转2
{
//TIMSK^=(1<<TOIE0);
key_state=2;
key_time1=0; //按下时间初始
}
else //按钮已经释放,消抖
key_state=0;
break;
case 2: //状态2:等待释放或等待按下时间达到长按要求
if(!key_press) //按钮已经释放,转3,继续判断是双按还是单按
{
key_state=3;
key_time0=0; //释放时间初始
}
else if (++key_time1>=100) //按下时间达到1000ms,返回值2,作长按判断,转7等待按钮释放
{
key_state=8;
key_time1=0;
key_return=2;
}
break;
case 8:
if(!key_press)
{
key_state=0;
key_time1=0;
}
else if (++key_time1>=50)
{
key_return=2;
key_time1=0;
}
break;
case 3: //状态3:双按的第二次按钮输入前的等待间隙,设定100ms(经过测试,100ms为比较合适的时间间隙,即为人体普通可以双击的速度
if(key_press)key_state=4; //在此时间,如果有按钮被按下,将当作释放抖动,转4进一步作出判断
else if (++key_time0>4) //如果没有按钮被按下,则等待此100ms过去,然后转5
{
key_state=5;
key_time0=0;
}
break;
case 4: //状态4:第二按的消抖处理
if(key_press)key_state=2; //快速连按(被认为人手指达不到要求的速率)将被返回到2,当作第一按处理
else key_state=3; //如果第二按只出现一次,不到10ms,消抖
break;
case 5: //状态5:第二按前等待时间到达,进入正常的第二按等待输入状态,第二按只允许在此时间内输入方为有效
if(key_press)key_state=6; //此时间内有被按下,转6,判决抖动;
else if(++key_time0>14) //无输入,则等待输入有效时间过去,时间满后,判定为单按,返回值1,状态位回到0
{
key_state=0;
key_time0=0; //双击间隔时间一般为100ms,能够稳定做到第二击完成时间总共约180~200ms(因人而异)
key_return=1; //为增加采样成功率,可适当缩短第二按前的间隙时间,增加第二按等待输入时间,但总时间不可短于150ms
} //小于150ms,手指将很难达到双击的速度要求,如果时间太长则单按判断时间过长,按钮不灵敏,此处180ms经测试较为合适
break;
case 6: //状态6:第二按的抖动判断
if(key_press) //按钮仍有效,按下有效,返回3,双按成立,转7等待按钮释放
{
key_state=7;
key_return=3;
}
else key_state=5; //抖动消除,退回5继续等待输入或等待输入有效时间过去
case 7: //按钮释放等待状态,所有已按下并被识别 *** 作目的的按钮状态都将转到7等待按钮释放,并将所有计时初始
if(!key_press)key_state=0;
key_time1=0;
key_time0=0;
break;
}
return key_return;
}
int main(void)
{
MCU_init();
timer0_init();
timer1_init();
timer2_init();
sei();
while(1)
{
if(timeOK)
{
cli();
uchar key;
key=key_scan();
if(key>0)PORTD=seg_code[key];
switch(key)
{
case 1:
TIMSK^=((1<<OCIE0)|(1<<TOIE1)); DDRB^=(1<<DDB3); PORTC=0xfd;
break;
case 2:
//TIMSK|=((1<<OCIE0)&(1<<TOIE1));
if(i>1)i+=10;
if (i>=(sizeof(music)-20))
{
i=1;
TIMSK&=(~((1<<OCIE0)|(1<<TOIE1)));
DDRB&=~(1<<DDB3);
}
PORTC=0xf0;
break;
case 3:
TIMSK&=(~((1<<OCIE0)|(1<<TOIE1)));
i=1;
TIMSK|=((1<<OCIE0)|(1<<TOIE1));
PORTC=0xfe;
break;
default:
break;
}
timeOK=0;
sei();
}
}
}
Web Service 元数据注释(JSR 181)
@WebService
1、serviceName: 对外发布的服务名,指定 Web Service 的服务名称:wsdl:service。缺省值为 Java 类的简单名称 + Service。(字符串)
2、endpointInterface: 服务接口全路径, 指定做SEI(Service EndPoint Interface)服务端点接口
3、name:此属性的值包含XML Web Service的名称。在默认情况下,该值是实现XML Web Service的类的名称,wsdl:portType 的名称。缺省值为 Java 类或接口的非限定名称。(字符串
4、portName: wsdl:portName。缺省值为 WebServicename+Port。
5、targetNamespace:指定你想要的名称空间,认是使用接口实现类的包名的反缀
6、wsdlLocation:指定用于定义 Web Service 的 WSDL 文档的 Web 地址。Web 地址可以是相对路径或绝对路径。(字符串)
注意:实现类上可以不添加Webservice注解
@WebMethod
注释表示作为一项 Web Service *** 作的方法,将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,或者应用于 JavaBeans 端点的服务器端点实现类。
要点:
仅支持在使用 @WebService 注释来注释的类上使用 @WebMethod 注释
1、operationName:指定与此方法相匹配的wsdl:operation 的名称。缺省值为 Java 方法的名称。(字符串)
2、action:定义此 *** 作的行为。对于 SOAP 绑定,此值将确定 SOAPAction 头的值。缺省值为 Java 方法的名称。(字符串)
3、exclude:指定是否从 Web Service 中排除某一方法。缺省值为 false。(布尔值)
@Oneway
注释将一个方法表示为只有输入消息而没有输出消息的 Web Service 单向 *** 作。
将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,或者应用于 JavaBeans 端点的服务器端点实现类
@WebParam
注释用于定制从单个参数至 Web Service 消息部件和 XML 元素的映射。
将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,或者应用于 JavaBeans 端点的服务器端点实现类。
1、name :参数的名称。如果 *** 作是远程过程调用(RPC)类型并且未指定partName 属性,那么这是用于表示参数的 wsdl:part 属性的名称。
如果 *** 作是文档类型或者参数映射至某个头,那么 -name 是用于表示该参数的 XML 元素的局部名称。如果 *** 作是文档类型、
参数类型为 BARE 并且方式为 OUT 或 INOUT,那么必须指定此属性。(字符串)
2、partName:定义用于表示此参数的 wsdl:part属性的名称。仅当 *** 作类型为 RPC 或者 *** 作是文档类型并且参数类型为BARE 时才使用此参数。(字符串)
3、targetNamespace:指定参数的 XML 元素的 XML 名称空间。当属性映射至 XML 元素时,仅应用于文档绑定。缺省值为 Web Service 的 targetNamespace。(字符串)
4、mode:此值表示此方法的参数流的方向。有效值为 IN、INOUT 和 OUT。(字符串)
5、header:指定参数是在消息头还是消息体中。缺省值为 false。(布尔值)
@WebResult
注释用于定制从返回值至 WSDL 部件或 XML 元素的映射。将此注释应用于客户机或服务器服务端点接口(SEI)上的方法,或者应用于 JavaBeans 端点的服务器端点实现类。
1、name:当返回值列示在 WSDL 文件中并且在连接上的消息中找到该返回值时,指定该返回值的名称。对于 RPC 绑定,这是用于表示返回值的 wsdl:part属性的名称。对于文档绑定,-name参数是用于表示返回值的 XML 元素的局部名。对于 RPC 和 DOCUMENT/WRAPPED 绑定,缺省值为 return。对于 DOCUMENT/BARE 绑定,缺省值为方法名 + Response。(字符串)
2、targetNamespace:指定返回值的 XML 名称空间。仅当 *** 作类型为 RPC 或者 *** 作是文档类型并且参数类型为 BARE 时才使用此参数。(字符串)
3、header:指定头中是否附带结果。缺省值为false。(布尔值)
4、partName:指定 RPC 或 DOCUMENT/BARE *** 作的结果的部件名称。缺省值为@WebResultname。(字符串)
@HandlerChain
注释用于使 Web Service 与外部定义的处理程序链相关联。只能通过对 SEI 或实现类使用 @HandlerChain 注释来配置服务器端的处理程序。
但是可以使用多种方法来配置客户端的处理程序。可以通过对生成的服务类或者 SEI 使用 @HandlerChain 注释来配置客户端的处理程序。此外,可以按程序在服务上注册您自己的 HandlerResolver 接口实现,或者按程序在绑定对象上设置处理程序链。
1、file:指定处理程序链文件所在的位置。文件位置可以是采用外部格式的绝对 javanetURL,也可以是类文件中的相对路径。(字符串)
2、name:指定配置文件中处理程序链的名称。
来源:>
程序自删除的方式有很多,不过最终的思想不过是关闭本身进程,开启新进程用于删除自身。下面这个方法是用windows自带命令行程序实现删除。
命令行为 cmdexe /c del filename
--------------------------------------------------------------------------------
代码示例:C语言形式
#include
#include
#include
BOOL SelfDel()
{
SHELLEXECUTEINFO sei;
TCHAR szModule [MAX_PATH],szComspec[MAX_PATH],szParams [MAX_PATH];
// 获得自身文件名 获取cmd的全路径文件名
if((GetModuleFileName(0,szModule,MAX_PATH)!=0) &&
(GetShortPathName(szModule,szModule,MAX_PATH)!=0) &&
(GetEnvironmentVariable("COMSPEC",szComspec,MAX_PATH)!=0))
{
// 设置命令参数
lstrcpy(szParams,"/c del ");
lstrcat(szParams, szModule);
lstrcat(szParams, " > nul");
// 设置结构成员
seicbSize = sizeof(sei);
seihwnd = 0;
seilpVerb = "Open";
seilpFile = szComspec;
seilpParameters = szParams;
seilpDirectory = 0; seinShow = SW_HIDE;
seifMask = SEE_MASK_NOCLOSEPROCESS;
// 创建cmd进程
if(ShellExecuteEx(&sei))
{
// 设置cmd进程的执行级别为空闲执行,使本程序有足够的时间从内存中退出
SetPriorityClass(seihProcess,IDLE_PRIORITY_CLASS);
// 将自身进程的优先级置高
SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);
// 通知Windows资源浏览器,本程序文件已经被删除
SHChangeNotify(SHCNE_DELETE,SHCNF_PATH,szModule,0);
return TRUE;
}
}
return FALSE;
}
---------------------------------------------------------------------------------
#include <avr/ioh>
#include <avr/interrupth>
#define uchar unsigned char
#define uint unsigned int
#define LED_ctrl PORTB //列开关
#define LED_code PORTD //行扫描代码
uchar code[8];
uchar str[]={0x00,0x90,0x90,0xF0,0x90,0x90,0x90,0x00, //H
0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00, //o
0x00,0x00,0xA8,0xA8,0xA8,0x50,0x50,0x00, //w
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //
0x00,0x00,0x60,0x90,0x90,0x90,0x68,0x00, //a
0x00,0x00,0xD8,0x60,0x40,0x40,0x40,0x00, //r
0x00,0x00,0x60,0x90,0xF0,0x80,0x60,0x00, //e
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //
0x00,0x90,0x90,0x90,0x70,0x10,0x60,0x00, //y
0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00, //o
0x00,0x00,0x90,0x90,0x90,0x90,0x68,0x00, //u
0x00,0x60,0x90,0x10,0x60,0x40,0x00,0x40, //
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //
volatile uchar flag_10ms=0,flag_move=0;
uchar i=0;
//动态扫描,显示一屏
void LED_dis(uchar word[])
{
for(uchar l=0;l<8;l++)
{
LED_ctrl=0xff;
LED_code=~word[l];
LED_ctrl=~(0x01<<l);
}
LED_ctrl=0xff;
}
//单片机初始化
void MCU_init(void)
{
DDRB=0Xff;
DDRD=0Xff;
LED_ctrl=0xff;
LED_code=0xff;
}
//中断计时初始化
void timer0_init(void)
{
TCNT0=100;
TCCR0=0x02;
TIMSK|=(1<<TOIE0);
}
//中断服务程序,这里设置时有些随意,大概是125ms一个周期
ISR(TIMER0_OVF_vect)
{
static uchar k=0;
TCNT0=100;
flag_10ms=1; //每中断扫描一次,即LED屏点亮一次,如要加大LED亮度,可适当修改以增加点空比
if(++k>=100)
{
flag_move=1; //100中断约125毫秒间隔标志位,每次移动字幕一列,速度可由K调节
k=0; //这里本不该有注释,但是居然忘记了初始化,整整查错查了将近一个半小时,楞是没看出来忘记初始化,要命啊
}
}
int main(void)
{
MCU_init();
timer0_init();
sei();
while(1)
{
if(flag_move==1)
{
uchar a,b;
flag_move=0;
if(i++==106)i=0;
a=i/8;
b=i%8;
for(uchar j=0;j<8;j++)
{
code[j]=(str[a8+j]<<b)|(str[a8+j+8]>>(8-b)); //这个程序最费工夫就是这个公式,移屏的算法,详细见程序后
}
}
else if(flag_10ms==1)
{
flag_10ms=0;
LED_dis(code);
}
}
}
//第一次玩LED点阵,花了很长时间总算搞定,起先用二维数组,用起来发现自己对二维数组和指针不熟,又整合成一维
//移屏公式请注意,因为我这个屏采用是的列开关,行扫描,移屏采用横移(左右平移),所以公式相对复杂一些,
//如果是上下纵移,或者是行开关列扫描的横移,应该相对会简单一些,只要在显示一屏的子函数中将位置错开一个即可
//本程序在GCC,mega16最小系统板上测试通过,51请自行改动中断接口以及输出端口即可,没用到AVR专有特性
以上就是关于是一测速程序 现在问题是如果脉冲信号突然为0了,要显示速度为0怎么办,程序该怎么改全部的内容,包括:是一测速程序 现在问题是如果脉冲信号突然为0了,要显示速度为0怎么办,程序该怎么改、avr单片机 在中断函数了改变全局变变量的值,发生很奇怪的事情,在这里向各位高手请教了,谢谢,源程序如、向单片机高手求助,怎样用C语言编写歌曲程序和歌曲代码需要用那些工具怎么样编写的要求详细解答。谢谢!等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)