┊ 网站导航 ┊ 管理登陆 ┊ 免责声明 ┊ 问题反馈 ┊ 友链说明┊本站部分内容来自网络共享资源,如有冒犯您的权利请来信告之删除或纠正! 不得对本站进行复制、盗链或镜像,转载内容须获得同意或授权;欢迎友情链接、站务合作! ![]() ![]() ![]() ![]() ![]() ![]() 本站学习交流群:138..158(高级群1-满)、77930286(高级群2)、61804809(群3) Copyright© MCUSY All Rights Reserved 本站网警备案号: WZ36040002485 ICP备案证书号:粤ICP备09034963号 |
#include<msp430x417.h>
#include"led.c"
#include"lcd_modle.c" //将其他的函数模块包涵在一个文件中
#define uchar unsigned char
#define uint unsigned int
#define TIME 6000 //延时时间常数,延时时间为183ms,其实延时时间常数完全可以设置得小一些,但是由于按键抖动得厉害,所以设这么大
//在IAR EW430 编译器软件中如何实现高精度软件延时,利用IAR EW430 内部延时子程序即可方便地实现
#define CPU_F ((double)1048576) //这里是你当前MSP430 CPU的主频频率,即CPU的MCLK,单位为HZ
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
//************************************************************************
//要发送的数据,用关键字"const" 声明,不放在RAM区
const uchar a[6]={0x66,0x83,0x08,0x00,0xE8,0x84}; //加号
const uchar b[6]={0x66,0x83,0x20,0x00,0xF6,0x84}; // 减号
const uchar c[6]={0x66,0x83,0x10,0x00,0xE2,0x84}; //左箭头
const uchar d[6]={0x66,0x83,0x18,0x00,0xE5,0x44}; //右箭头
const uchar e[6]={0x66,0x83,0x28,0x00,0xF1,0x44}; //OK
const uchar f[6]={0x66,0x83,0x30,0x00,0xFB,0x44}; //C/II
const uchar g[6]={0x66,0x83,0x38,0x00,0xFC,0x84}; //开阀
const uchar h[6]={0x66,0x83,0x40,0x00,0xDE,0x84}; //关阀
const uchar i[6]={0x66,0x83,0x48,0x00,0xD9,0x44}; //左右箭头同时按下
extern void lcd_modle(); //利用函数原型(函数声明)扩展函数的作用域,
void led(); //利用函数原型(函数声明)扩展函数的作用域, extern可以省略
uchar keybuf=0x00; //键值,全局变量的初始化
uchar keytime=0x06; //判断连键时,定时中断的次数,初始化为6,即连键时间间隔设置
//************************************************************************
void settime(long uint ti) //设置定时时间
{
CCR0=ti; //定时时间
}
void gostopA(uchar a) //打开或是关闭定时器,其中a为判断标志
{
if(a==1)
{
TACTL=TASSEL0+TACLR+MC0; //清TAR(消除定时器的方向记忆特性),设置定时器工作在增计数模式,记得选择ASCLK作为定时时钟
settime(TIME);
}
else if(a==0)
{
TACTL&=~MC0; //定时器暂停计数,TACTL=MC_0;但是并不发生复位,当定时器重新计数时,计数器从暂停时的值开始
}
}
//************************************************************************
void timerainit() //定时器A的初始化
{
TACTL=TASSEL0+TACLR; //选ASCLK,清TAR, 刚开始并没有计数
CCTL0=CCIE; //先开允许比较中断
settime(TIME); //设置时间放在允许中断的后面
}
//************************************************************************
void gostopkey(uchar sw) //打开或者关闭按键中断
{
if(sw==0)
P1IE&=0X00; //关闭按键中断
else if (sw==1)
P1IE|=0XFF; //打开按键中断允许
}
//************************************************************************
uchar conkey() //连续按键的判断和处理,此模块放在定时中断程序中,不知是否需要清定时中断标志(CCIFG0=0;),不需要消除,它会自动消除,跳出定时中断
{
uchar x=0x00;
if((P1IN&0XFF)==0X00) //单独按键,或者是连续按键松开之后
{ //没有键按下
gostopA(0); //关闭定时器
gostopkey(1); //打开按键中断
}
else //连续按键的情况
{
if(keytime==0) //连续按键的时间到
{
keytime=0x06; //重新置值
if((P1IN&0XFF)==0X80)
{
x=1; //给全局变量键值赋值
}
else if((P1IN&0XFF)==0X40)
{
x=2;
}
else if((P1IN&0XFF)==0X20)
{
x=3;
}
else if((P1IN&0XFF)==0X10)
{
x=6;
}
else if((P1IN&0XFF)==0X08)
{
x=4;
}
else if((P1IN&0XFF)==0X04)
{
x=7;
}
else if((P1IN&0XFF)==0X02)
{
x=5;
}
else if((P1IN&0XFF)==0X01)
{
x=8;
}
else if((P1IN&0XFF)==0X18) //组合键,4、6组合键,组合键有效的时间为:按键之后:183ms*6,即时间间隔为连键时间间隔
{
x=9;
}
else //其他情况
{
x=0x00;
gostopA(0); //关闭定时器
gostopkey(1); //打开按键中断
}
}
else //连续按键的时间没有到
keytime--;
}
return(x);
}
//************************************************************************
#pragma vector=TIMERA0_VECTOR //CCRO中断,为单源中断,自动消除中断标志
__interrupt void Timer_A0(void) //定时器中断
{
keybuf=conkey(); //获取连续按键值,0x00代表没有连续按键
}
//************************************************************************
void keyinit() //按键初始化
{
P1DIR&=0X00; //P1口接8个按键,全部设为输入
P1IES&=0X00; //设为上升沿中断
P1IE|=0XFF; //全部允许中断
P1IFG&=0X00; //清中断标
}
//************************************************************************
uchar keycode() //判断单个的键值
{
uchar y, q0=0;
if((P1IN&0XFF)==0X80)//不使用中断标志查询中断源,在按键中断中不识别组合键
{
y=1; q0=1;
}
else if((P1IN&0XFF)==0X40)
{
y=2; q0=1;
}
else if((P1IN&0XFF)==0X20)
{
y=3; q0=1;
}
else if((P1IN&0XFF)==0X10)
{
y=6; q0=1;
}
else if((P1IN&0XFF)==0X08)
{
y=4; q0=1;
}
else if((P1IN&0XFF)==0X04)
{
y=7; q0=1;
}
else if((P1IN&0XFF)==0X02)
{
y=5; q0=1;
}
else if((P1IN&0XFF)==0X01)
{
y=8; q0=1;
}
else
y=0x00; //没有按键按下,或者是其他情况
if(q0==1) //有按键按下的情况,为判断是否按键连续做准备
{
gostopA(1); //开启定时中断
gostopkey(0); //关闭按键中断
}
return(y);
}
//************************************************************************
#pragma vector=PORT1_VECTOR
__interrupt void port1_vector(void)
{
keybuf=keycode();
P1IFG=0X00;//消除中断标志,跳出按键中断
}
//************************************************************************
void zijiesend(uchar m) //以19200bit/S红外发送一个字节,
{
uchar n;
P5OUT&=0xdf;P5OUT|=0X20;delay(4);_NOP();_NOP();_NOP();//发送起始位,设置波特率
for(n=1;n<=8;n++) //8个数据位,发8次
{
if((m&0x01)==0){P5OUT&=0Xdf;P5OUT|=0X20;delay(4);_NOP();} //先发最低位(即最右边那位)
else {P5OUT|=0X20;delay(6);}
m=m>>0x01; //将要发送的数据右移一位
}
P5OUT|=0x20; //发送停止位
delay(7);_NOP();_NOP();_NOP();_NOP();//延时1个停止位
}
//************************************************************************
void shuzusend(const uchar *c) //使用指针调用数组
{
uchar i,*p; //i为数组元素个数
p=(uchar *)c; //指针类型转换
keybuf=0x00; //清零
for(i=1;i<=6;i++) //数组有6个元素,发送6次
{
zijiesend(*p); //发送数组元素
p++; //移到下一个元素
delay_us(500); //发送完一个字节等待500微秒
}
delay_ms(10); //发送完一个数组等待10毫秒
}
//************************************************************************
main() //连续去抖动,按键机械扛抖动能力很差,加入了组合键(注意组合键识别的有效时键)
{
WDTCTL=WDTPW+WDTHOLD;//关看门狗
P2DIR|=0X04;
P2OUT|=0X04; //在P2.2口输出高电位,开启红外部分电源
keyinit(); //按键初始化
timerainit(); //定时器初始化
P5DIR|=0X20; //设置P5.5为输出端
delay_ms(150); //进入循环前延时,等待低速时钟稳定
_EINT(); //开总中断
while(1)
{
switch(keybuf) //使用keybuf作为判断标志
{
case 0x00 : break;
case 1 : shuzusend(a); break;
case 2 : shuzusend(b); break;
case 3 : shuzusend(c); break;
case 4 : shuzusend(d); break;
case 5 : shuzusend(e); break;
case 6 : shuzusend(f); break;
case 7 : shuzusend(g); break;
case 8 : shuzusend(h); break;
case 9 : shuzusend(i); break; //4、6组合键
default : break;
}
}
}
//定时器延时时间常数本来可以设得比较小的,但设置得小的时候,由于抖动厉害,会发两次数据;若是需要修改连键识别时间间隔,直接更改"keytime"的值就可以了
//低速时钟需要上百毫秒的建立时间才能稳定下来。
2、红外接收数组,并将接收到的数组以19200b/S的速率,经485发送PC串口,并在串口调试助手上显示出来:
#include<msp430x417.h>
#include"delay.c"
#define uchar unsigned char
#define uint unsigned int
//在IAR EW430 编译器软件中如何实现高精度软件延时,利用IAR EW430 内部延时子程序即
可方便地实现
#define CPU_F ((double)1048576) //这里是你当前MSP430 CPU的主频
频率,即CPU的MCLK,单位为HZ
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
//************************************************************************
uchar a[6]={0}; //定义数组a来存放红外接收到的数据,并初始化为0,
uchar zijiereceive()//用关系统总中断,查询中断标志的方案实现
{
uchar s,t=0x00;
for(;;) //没有字节发送则一直等待
if((P2IFG&0X01)==0X01)
{ P2IFG&=0XFE; //先将中断标志清零
break;
}
delay(10); //从检测到起始位(下降沿)到第一个采样点的延时
if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;}
else {s=0x01;P2IFG&=0XFE;}
t+=s;
delay(7);
if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;}
else {s=0x01;P2IFG&=0XFE;}
s<<=1;
t+=s;
delay(7);
if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;}
else{s=0x01;P2IFG&=0XFE;}
s<<=2;
t+=s;
delay(4);
if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;}
else {s=0x01;P2IFG&=0XFE;}
s<<=3;
t+=s;
delay(4);
if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;}
else {s=0x01;P2IFG&=0XFE;}
s<<=4;
t+=s;
delay(3);
if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;}
else {s=0x01;P2IFG&=0XFE;}
s<<=5;
t+=s;
delay(3);
if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;}
else {s=0x01;P2IFG&=0XFE;}
s<<=6;
t+=s;
delay(6);
if((P2IFG&0X01)==0X01){s=0x00;P2IFG&=0XFE;}
else {s=0x01;P2IFG&=0XFE;}
s<<=7;
t+=s;
return(t);
}
//************************************************************************
void shuzureceive( uchar *a) //使用指针完成一个数组的接收,并将他们按顺序存入
已定义的数组。
{ uchar i,*p; //定义循环常数和指针变量
p=a; //将数组首地址赋给指针p
P2IES|=0X01; //P2.0设为下降沿中断触发
P2IFG&=0XFE; //将中断标志清零,初始化
for(i=1;i<=6;i++)
{
*p=zijiereceive(); //存入一个字节
p++; //更新存储单元
}
}
//************************************************************************
void transmit(uchar m) //485以19200bit/S发送一个字节,
{
uchar n;
P5OUT&=0xdf; //发送起始位
delay(6); //设置波特率
for(n=1;n<=8;n++) //8个数据位,发8次
{
if((m&0x01)==0)P5OUT&=0Xdf;//先发最低位(即最右边那位)
else P5OUT|=0X20;
delay(6);
m=m>>0x01; //将要发送的数据右移一位
}
P5OUT|=0x20; //发送停止位
delay(8);_NOP(); //延时1个停止位
}
//************************************************************************
void send( uchar *c) //使用指针调用数组,485发送一个数组
{
uchar i,*p; //i为数组元素个数
p=c; //指针类型转换
for(i=1;i<=6;i++) //数组有6个元素,发送6次
{
transmit(*p); //发送数组元素
p++; //移到下一个元素
}
}
//************************************************************************
main()
{
WDTCTL=WDTPW+WDTHOLD;//关看门狗
_DINT();//关总中断
P2DIR|=0X04;
P2OUT|=0X04; //输出高电平,开启红外部分电源,这也是用的P2口
P5DIR|=0X20; //设置P5.5为输出端
delay_ms(20); // 等待低速时钟稳定
while(1)
{ shuzureceive(a); //红外接收一个数组
send(a); //485发送接到的数据
}
}
//不允许中断,但中断标志仍然存在,须用软件清零
实验结果(串口助手上显示的数据):
00
66 83 38 00 FC 84
00
66 83 18 00 E5 44
66 83 18 00 E5 44
66 83 18 00 E5 44
66 83 18 00 E5 44
00
66 83 18 00 E5 44
66 83 18 00 E5 44
66 83 18 00 E5 44
00
66 83 38 00 FC 84
66 83 38 00 FC 84
00
66 83 30 00 FB 44
66 83 30 00 FB 44
00
00 00 00
00
66 83 08 00 E8 84
66 83 08 00 E8 84
66 83 08 00 E8 84
66 83 08 00 E8 84
00
66 83 20 00 F6 84
66 83 20 00 F6 84
66 83 20 00 F6 84
66 83 20 00 F6 84
┊ 网站导航 ┊ 管理登陆 ┊ 免责声明 ┊ 问题反馈 ┊ 友链说明┊本站部分内容来自网络共享资源,如有冒犯您的权利请来信告之删除或纠正! 不得对本站进行复制、盗链或镜像,转载内容须获得同意或授权;欢迎友情链接、站务合作! ![]() ![]() ![]() ![]() ![]() ![]() 本站学习交流群:138..158(高级群1-满)、77930286(高级群2)、61804809(群3) Copyright© MCUSY All Rights Reserved 本站网警备案号: WZ36040002485 ICP备案证书号:粤ICP备09034963号 |