基于MSP430单片机的菜单程序设计思路,以及简单示例,最好C语言程序!

基于MSP430单片机的菜单程序设计思路,以及简单示例,最好C语言程序!,第1张

我以前倒是做过,不过程序还有点问题,调时间的时候容易过界,但正常走时候就正常了。开发环境用的IAR,单片机用f149,显示用的1602的四线模式。

你自己看着改程序吧,其实我也是51上移植过去的。

悲剧了,帖不下了我帖在我博客里了啊,自己去找吧

主程序

__________________________分隔线____________________________________

#include <msp430x14xh>

#include "ds1302h"

#include "LCD1602x4_mpsh"

#define DS1302_SECOND 0x81 //时钟芯片的寄存器位置,存放时间

#define DS1302_MINUTE 0x83

#define DS1302_HOUR 0x85

#define DS1302_WEEK 0x8b

#define DS1302_DAY 0x87

#define DS1302_MONTH 0x89

#define DS1302_YEAR 0x8d

unsigned char DateString[11],TimeString[9],week_value[2],TempBuffer[7]; //

char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year;

char done,count,temp,flag,up_flag,down_flag;

//unsigned int temp_value=0,temp_max=0;temp_min=0; //温度值

void DateToStr(void) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]

{ unsigned char Year,Month,Day,Week;

Year=rtc_getyear();

Month=rtc_getmon();

Day=rtc_getdate();

Week=rtc_getday();

if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22

{

DateString[0] = '2';

DateString[1] = '0';

DateString[2] = Year/10 + '0';

DateString[3] = Year%10 + '0';

}

else

{

DateString[0] = ' ';

DateString[1] = ' ';

DateString[2] = ' ';

DateString[3] = ' ';

}

DateString[4] = '/';

if(hide_month<2)

{

DateString[5] = Month/10 + '0';

DateString[6] = Month%10 + '0';

}

else

{

DateString[5] = ' ';

DateString[6] = ' ';

}

DateString[7] = '/';

if(hide_day<2)

{

DateString[8] = Day/10 + '0';

DateString[9] = Day%10 + '0';

}

else

{

DateString[8] = ' ';

DateString[9] = ' ';

}

if(hide_week<2)

{

week_value[0] = Week%10 + '0'; //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示

}

else

{

week_value[0] = ' ';

}

week_value[1] = '\0';

DateString[10] = '\0'; //字符串末尾加 '\0' ,判断结束字符

}

void TimeToStr(void) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];

{ unsigned char Hour,Minute,Second;

Hour=rtc_gethour();

Minute=rtc_getmin();

Second=rtc_getsec();

if(hide_hour<2)

{

TimeString[0] = Hour/10 + '0';

TimeString[1] = Hour%10 + '0';

}

else

{

TimeString[0] = ' ';

TimeString[1] = ' ';

}

TimeString[2] = ':';

if(hide_min<2)

{

TimeString[3] = Minute/10 + '0';

TimeString[4] = Minute%10 + '0';

}

else

{

TimeString[3] = ' ';

TimeString[4] = ' ';

}

TimeString[5] = ':';

if(hide_sec<2)

{

TimeString[6] = Second/10 + '0';

TimeString[7] = Second%10 + '0';

}

else

{

TimeString[6] = ' ';

TimeString[7] = ' ';

}

DateString[8] = '\0';

}

void show_time() //液晶显示程序

{

TimeToStr(); //时间数据转换液晶字符

DateToStr(); //日期数据转换液晶字符

// ReadTemp(); //开启温度采集程序

// temp_to_str(); //温度数据转换成液晶字符

LCD_PutStr(TempBuffer,25); //显示温度

LCD_PutStr(DateString,0); //显示日期

LCD_PutStr(week_value,15); //显示星期

LCD_PutStr(" Week",10); //在液晶上显示 字母 week

LCD_PutStr(TimeString,16); //显示时间

}

////////////////////////////////////////////////////////////////////////////

void outkey() //跳出调整模式,返回默认显示

{ unsigned char Second;

if (!(P1IN&BIT0))

{

count=0;

hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0;

Second=dataread(DS1302_SECOND);

datawrite(0x8e,0x00); //写入允许

datawrite(0x80,Second&0x7f);

datawrite(0x8E,0x80); //禁止写入

done=0;//temp_max=0;sund=1;

while(!(P1IN&BIT0));

delay_nms(2);

}

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Upkey()//升序按键

{

if(!(P1IN&BIT1))

{

switch(count)

{case 1:

temp=dataread(DS1302_SECOND); //读取秒数

temp=temp+1; //秒数加1

up_flag=1; //数据调整后更新标志

if((temp&0x7f)>0x59) //超过59秒,清零

temp=0;

break;

case 2:

temp=dataread(DS1302_MINUTE); //读取分数

temp=temp+1; //分数加1

up_flag=1;

if(temp>0x59) //超过59分,清零

temp=0;

break;

case 3:

temp=dataread(DS1302_HOUR); //读取小时数

temp=temp+1; //小时数加1

up_flag=1;

if(temp>0x23) //超过23小时,清零

temp=0;

break;

case 4:

temp=dataread(DS1302_WEEK); //读取星期数

temp=temp+1; //星期数加1

up_flag=1;

if(temp>0x7)

temp=1;

break;

case 5:

temp=dataread(DS1302_DAY); //读取日数

temp=temp+1; //日数加1

up_flag=1;

if(temp>0x31)

temp=1;

break;

case 6:

temp=dataread(DS1302_MONTH); //读取月数

temp=temp+1; //月数加1

up_flag=1;

if(temp>0x12)

temp=1;

break;

case 7:

temp=dataread(DS1302_YEAR); //读取年数

temp=temp+1; //年数加1

up_flag=1;

if(temp>0x99)

temp=0;

break;

default:break;

}

while(!(P1IN&BIT1));

delay_nms(2);

}

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Downkey()//降序按键

{

if(!(P1IN&BIT2))

{

switch(count)

{case 1:

temp=dataread(DS1302_SECOND); //读取秒数

temp=temp-1; //秒数减1

down_flag=1; //数据调整后更新标志

if((temp&0x7f)>0x59) //小于0秒,返回59秒

temp=0x59;

break;

case 2:

temp=dataread(DS1302_MINUTE); //读取分数

temp=temp-1; //分数减1

down_flag=1;

if(temp>0x59)

temp=0x59; //小于0秒,返回59秒

break;

case 3:

temp=dataread(DS1302_HOUR); //读取小时数

temp=temp-1; //小时数减1

down_flag=1;

if(temp==0x00)

temp=0x23;

break;

case 4:

temp=dataread(DS1302_WEEK); //读取星期数

temp=temp-1; //星期数减1

down_flag=1;

if(temp==0x00)

temp=0x07;

break;

case 5:

temp=dataread(DS1302_DAY); //读取日数

temp=temp-1; //日数减1

down_flag=1;

if(temp==0x00)

temp=0x31;

break;

case 6:

temp=dataread(DS1302_MONTH); //读取月数

temp=temp-1; //月数减1

down_flag=1;

if(temp==0x00)

temp=0x12;

break;

case 7:

temp=dataread(DS1302_YEAR); //读取年数

temp=temp-1; //年数减1

down_flag=1;

if(temp>0x99)

temp=0x99;

break;

default:break;

}

while(!(P1IN&BIT2));

delay_nms(2);

}

}

void Setkey()//模式选择按键

{

if(!(P1IN&BIT3))

{

count=count+1; //Setkey按一次,count就加1

done=1; //进入调整模式

while(!(P1IN&BIT3));

delay_nms(2);

}

}

void keydone()//按键功能执行

{ unsigned char Second;

if(flag==0) //关闭时钟,停止计时

{ datawrite(0x8e,0x00); //写入允许

temp=dataread(DS1302_SECOND);

datawrite(0x80,temp|0x80);

datawrite(0x8e,0x80); //禁止写入

flag=1;

}

Setkey(); //扫描模式切换按键

switch(count)

{

case 1:do //count=2,调整秒

{

outkey(); //扫描跳出按钮

Upkey(); //扫描加按钮

Downkey(); //扫描减按钮

if(up_flag==1||down_flag==1) //数据更新,重新写入新的数据

{

datawrite(0x8e,0x00); //写入允许

datawrite(0x80,temp|0x80); //写入新的秒数

datawrite(0x8e,0x80); //禁止写入

up_flag=0;

down_flag=0;

}

hide_sec++; //位闪计数

if(hide_sec>3)

hide_sec=0;

show_time(); //液晶显示数据

}while(count==2);break;

case 2:do //count=3,调整分

{

hide_sec=0;

outkey();

Upkey();

Downkey();

if(temp>0x60)

temp=0;

if(up_flag==1||down_flag==1)

{

datawrite(0x8e,0x00); //写入允许

datawrite(0x82,temp); //写入新的分数

datawrite(0x8e,0x80); //禁止写入

up_flag=0;

down_flag=0;

}

hide_min++;

if(hide_min>3)

hide_min=0;

show_time();

}while(count==3);break;

case 3:do //count=4,调整小时

{

hide_min=0;

outkey();

Upkey();

Downkey();

if(up_flag==1||down_flag==1)

{

datawrite(0x8e,0x00); //写入允许

datawrite(0x84,temp); //写入新的小时数

datawrite(0x8e,0x80); //禁止写入

up_flag=0;

down_flag=0;

}

hide_hour++;

if(hide_hour>3)

hide_hour=0;

show_time();

}while(count==4);break;

case 4:do //count=5,调整星期

{

hide_hour=0;

outkey();

Upkey();

Downkey();

if(up_flag==1||down_flag==1)

{

datawrite(0x8e,0x00); //写入允许

datawrite(0x8a,temp); //写入新的星期数

datawrite(0x8e,0x80); //禁止写入

up_flag=0;

down_flag=0;

}

hide_week++;

if(hide_week>3)

hide_week=0;

show_time();

}while(count==5);break;

case 5:do //count=6,调整日

{

hide_week=0;

outkey();

Upkey();

Downkey();

if(up_flag==1||down_flag==1)

{

datawrite(0x8e,0x00); //写入允许

datawrite(0x86,temp); //写入新的日数

datawrite(0x8e,0x80); //禁止写入

up_flag=0;

down_flag=0;

}

hide_day++;

if(hide_day>3)

hide_day=0;

show_time();

}while(count==6);break;

case 6:do //count=7,调整月

{

hide_day=0;

outkey();

Upkey();

Downkey();

if(up_flag==1||down_flag==1)

{

datawrite(0x8e,0x00); //写入允许

datawrite(0x88,temp); //写入新的月数

datawrite(0x8e,0x80); //禁止写入

up_flag=0;

down_flag=0;

}

hide_month++;

if(hide_month>3)

hide_month=0;

show_time();

}while(count==7);break;

case 7:do //count=8,调整年

{

hide_month=0;

outkey();

Upkey();

Downkey();

if(up_flag==1||down_flag==1)

{

datawrite(0x8e,0x00); //写入允许

datawrite(0x8c,temp); //写入新的年数

datawrite(0x8e,0x80); //禁止写入

up_flag=0;

down_flag=0;

}

hide_year++;

if(hide_year>3)

hide_year=0;

show_time();

}while(count==8);break;

case 8: count=0;hide_year=0; //count8, 跳出调整模式,返回默认显示状态

Second=dataread(0x80);

datawrite(0x8e,0x00); //写入允许

datawrite(0x80,Second&0x7f);

datawrite(0x8E,0x80); //禁止写入

done=0; //temp_max=0;sund=1;

break; //count=7,开启中断,标志位置0并退出

default:break;

}

}

////////////////////////////////////////////////////////////////////////////

void rtcinit ()

{

rtc_wp(0);

rtc_stop(0);

rtc_charger(1,1);

}

void sysinit ()

{ WDTCTL = WDTPW + WDTHOLD; //关闭看门狗

P4OUT = 0xff;

P4DIR = 0xff;

P5OUT = 0x0f;

P5DIR = 0xf0;

P6OUT = 0xfc;

P6DIR = 0xfc;

}

void main ()

{ unsigned char temp;

sysinit ();

rtcinit ();

LCD_init(); //液晶初始化

_EINT();

while (1)

{

while(done==1)

keydone(); //进入调整模式

while(done==0)

{

temp=rtc_getsec();

delay_nms(10);

if(temp!=rtc_getsec())

show_time(); //液晶显示数据

flag=0;

Setkey(); //扫描各功能键

}

}

}

sbit  GO_OUT =P3^5;                       //需要检测的引脚

sbit  LED         =P3^4;                       //显示led    引脚为低时候亮

void main()                     //主程序

{

while(1)                    //主循环

{

if(GO_OUT==0)

{

LED=1;                            //引脚为低 led不亮

}

else      LED=0;          // 否则led点亮

}

}

#include<reg51h>

#define uchar unsigned char

uchar tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};  //0到9

uchar num,cnt,disn;

uchar keyval,disk;

uchar led[]={1,2,3,4};

void dealdat(uchar a)

{

led[0]=0;

led[1]=0;

led[2]=0;

led[3]=0;

led[a]=disk;

}

void delay(unsigned int a)

{

unsigned int i,j;

for(i=0;i<a;i++)

for(j=0;j<1000;j++);

}

void t0isr() interrupt 1

{

TH0=(65536-5000)/256;

TL0=(65536-5000)%256;

switch(num)

{

case 0:P2=0x01;break;

case 1:P2=0x02;break;

case 2:P2=0x04;break;

case 3:P2=0x08;break;

default:break;

}

P0=~tab[led[num]];

num++;

num&=0x03;

cnt++;

if(cnt>100)

{

cnt=0;

disn++;

disn%=4;

dealdat(disn);

}

}

uchar kbscan(void)

{

unsigned char sccode,recode;

P3=0x0f;  //发0扫描,列线输入

if ((P3 & 0x0f) != 0x0f)  //有键按下

{

// delay(20);   //延时去抖动

if ((P3&0x0f)!= 0x0f)

{

sccode = 0xef;    //逐行扫描初值

while((sccode&0x01)!=0)

{

    P3=sccode;

if((P3&0x0f)!=0x0f)

{

    recode=(P3&0x0f)|0xf0;

return((~sccode)+(~recode));

 }

        else

sccode=(sccode<<1)|0x01;

}

}

}

return 0;  //无键按下,返回0

}

void getkey(void)

{

unsigned char key;

key=kbscan();

if(key==0){keyval=0xff;return;}

switch(key)

{

case 0x11:keyval=7;break;

case 0x12:keyval=4;break;

case 0x14:keyval=1;break;

case 0x18:keyval=10;break;

case 0x21:keyval=8;break;

case 0x22:keyval=5;break;

case 0x24:keyval=2;break;

case 0x28:keyval=0;break;

case 0x41:keyval=9;break;

case 0x42:keyval=6;break;

case 0x44:keyval=3;break;

case 0x48:keyval=11;break;

case 0x81:keyval=12;break;

case 0x82:keyval=13;break;

case 0x84:keyval=14;break;

case 0x88:keyval=15;break;

default:keyval=0xff;break;

}

}

main()

{

TMOD=0x11;

TH0=(65536-5000)/256;

TL0=(65536-5000)%256;

TR0=1;

ET0=1;

EA=1;

while(1)

{

getkey();

if(keyval!=0xff)disk=keyval;

delay(10);

}

}

你要 输出 也宽 的 买脉冲 。。。。。

#include <reg51h>

delay_ms(unsigned int )

{

……

}

void main()

{

P1=~P1;

delay_ms(1);

}

想知道哪种,给你粘贴,下面是一些计算子程序

;

;一、十六位二进制转换为BCD数子程序

;

MOVLW 10H ;

MOVWF CNT ;

BCF STATUS,C ;

CLRF R2 ;

CLRF R1 ;

CLRF R0 ;

LOOP RLF AL ;

RLF AH ;

RLF R0 ;

RLF R1 ;

RLF R2 ;

DECFSZ CNT ;

GOTO ADJDEC ;

RETURN

ADJDEC MOVLW R0 ;

MOVWF FSR ;

CALL ADJBCD ;

MOVLW R1 ;

MOVWF FSR ;

CALL ADJBCD ;

MOVLW R2 ;

MOVWF FSR ;

CALL ADJBCD ;

GOTO LOOP ;

ADJBCD MOVLW 3H ;

ADDWF INDF,W ;

MOVWF TMP ;

BTFSC TMP,3 ;

MOVWF INDF ;

MOVLW 30H ;

ADDWF INDF,W ;

MOVWF TMP ;

BTFSC TMP,7 ;

MOVWF INDF ;

RETURN

;

;乘法宏

;两个八位无符号数乘法,乘积为十六位。部分积右移相加算法:乘数带进位右移一位,

;检查进位是否为一,若是一,部分积寄存器加被乘数,否则不加;然后部分积寄存器

;带进位右移一位;重复上述过程直至循环次数为八结束。

;

;宏的引用格式:MUL A,B

;完成 *** 作: (A)(B)---(A,B)

;影响状态位:C、Z和DC

;88位乘法宏MUL,结果的高字节部分存入(A),低字节存入(B)

;

MUL MACRO A,B ;

LOCAL MLOOP ;

;

;如只用乘法子程序,就下段。

;

CLRF TMPA ;

CLRF TMPB ;

MOVLW 8 ;

MOVWF CNT ;

MOVF A,W ;

BCF STATUS,C ;

MLOOP RRF B ;

BTFSC STATUS,C ;

ADDWF TMPA ;

RRF TMPA ;

RRF TMPB ;

DECFSZ CNT ;

GOTO MLOOP ;

MOVF TMPA,W ;

MOVWF A ;

MOVF TMPB,W ;

MOVWF B ;

;

ENDM

;

;除法宏DIV

;除法是乘法的逆运算。与十进制长除法类似,从被除数的最高有效位开始,把被除数左移

;一位至余数上,如果余数不够减去除数,则商寄存器左移,移入位为零,反之移入位为一

;余数减去被除数,把被除数的下一位移至除数上。重复上述过程直至处理完所有位。

;

;宏的引用格式:DIV A,B

;完成 *** 作: (A)为商部分,(B)为余数部分

;影响状态位:C、Z和DC

;8/8位除法宏DIV,结果(A)为商部分,(B)为余数部分

;

DIV MACRO A,B ;

LOCAL MLOOP ;

;

;如只用除法子程序,就下段。

;

MOVF A,W ;

MOVWF TMPA ;

MOVF B,W ;

MOVWF TMPB ;

MOVLW 8 ;

MVOWF CNT ;

CLRF A ;

CLRF B ;

DLOOP BCF STATUS,C ;

RLF TMPA ;

RLF B ;

MOVF TMPB,W ;

SUBWF B,W ;

BTFSC STATUS,C ;

MOVWF B ;

RLF A ;

DECFSZ CNT ;

GOTO DLOOP ;

;

ENDM ;

;

;间接寻址

CLRF R0 ;清除R0寄存器里的内容

MOVLW R0 ;

MOVWF FSR ;将R0寄存器的地址送入间接寻址指针FSR

MOVF INDF,0 ;

MOWF TEMP ;将间接寻址指针FSR所指地址R0寄存器里的内容送入TEMP

MOVLW 88H ;

MOVWF INDF ;将88H送入间接寻址指针FSR所指地址R0寄存器里

;

;将两位BCD数送入显示

;显示十位BCD数

DISPLAY SWAPF TEMP,W ;将TEMP寄存器里的内容的高低字节交换并送入W

ANDLW 0FH ;将0FH与W寄存器里的内容相与并送入W

CALL CODE_TAB ;查表取段码

MOVWF PORTD ;送入PORTD端口

MOVLW 1H ;

MOVWF PORTC ;选通PORTC,1

CALL DELAY ;调用延时

;显示个位BCD数

MOVF TEMP,W ;

ANDLW 0FH ;

CALL CODE_TAB ;

MOVWF PORTD ;

MOVLW 2H ;

MOVWF PORTC ;

CALL DELAY ;

;

;16位二进制除以8位二进制

DIV16

MOVF A,0

MOVWF DIV_H

MOVF BX,0

MOVWF DIV_L ;被除数高低字节分别送进各寄存器

MOVLW 9H

MOVWF DIVB ;将除数送进寄存器

MOVLW 10H

MOVWF CNT ;按被除数位数设定移位次数

CLRF AL

CLRF AH

CLRF BX

DLOOP

BCF STATUS,C

RLF DIV_L

RLF DIV_H

RLF BX

MOVF DIVB,W

SUBWF BX,W

BTFSC STATUS,C

MOVWF BX

RLF AL

RLF AH

DECFSZ CNT

GOTO DLOOP

RETURN

;

;8位乘以16位二进制乘法运算程序

;

MUL8

CLRF TMPA ;清除积的高位寄存器

CLRF TMPB ;清除积的中位寄存器

CLRF TMPC ;清除积的低位寄存器

MOVLW 10H ;因为8位二进制乘以16位二进制,乘数为16位,移位乘数,所以移位次数为16次

MOVWF CNT ;

MOVF BX,W ;将8位被乘数送进W

BCF STATUS,C;

MLOOP RRF TEMP_H ;

RRF TEMP_L ;带C循环右移16位乘数

BTFSC STATUS,C ;

ADDWF TMPA ;

RRF TMPA ;

RRF TMPB

RRF TMPC

DECFSZ CNT ;

GOTO MLOOP ;

MOVF TMPA,W ;

MOVWF AA ;

MOVF TMPB,W ;

MOVWF A

MOVF TMPC,W ;将乘积送进各寄存器。

MOVWF BX

RETURN

有PWM功能的单片机入STC12系列单片机,直接给专用寄存器赋值开启相应定时器就可以了。普通单单片机,PWM需要用自己来调配。比如:

#include<reg51h>

unsigned char pwhh,pwhl,pwlh,pwll;

bit flag;

sbit pwm=P1^0;

void t0isr() interrupt 1

{

if(flag)

{

TH0=pwhh;

TL0=pwhl;

}

else

{

TH0=pwlh;

TL0=pwll;

}

pwm=~pwm;

}

main()

{

TMOD=0x01;

pwhh=(65536-1000)/256;

pwhl=(65536-1000)%256;

pwlh=(65536-500)/256;

pwll=(65536-500)%256;

TH0=pwhh;

L0=pwhl;

TR0=1;

ET0=1;

EA=1;

while(1);

}

以上就是关于基于MSP430单片机的菜单程序设计思路,以及简单示例,最好C语言程序!全部的内容,包括:基于MSP430单片机的菜单程序设计思路,以及简单示例,最好C语言程序!、51单片机 如何检测某个引脚是否为高低电平 求一个C源程序实例、c51单片机程序实例等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9849545.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-02
下一篇 2023-05-02

发表评论

登录后才能评论

评论列表(0条)

保存