一二三亖

    1. msp430学习笔记

      标签:msp430

      一,MSP430G2553单片机的各个功能模块 ??(一),IO口模块, ??1,我们所用的MSP430G2553有两组IO口,P1和P2。 ??2,IO口的寄存器有:方向选择寄存器PxDIR,输出寄存器PxOUT,输入寄存器PxIN,IO口内部上拉或下拉电阻使能寄存器PxREN,?IO口功能选择寄存器PxSEL和PxSEL2,IO口中断使能寄存器PxIE,中断沿选择寄存器PxIES,IO口中断标志寄存器PxIFG。 ??3,所有的IO都带有中断,其中所有的P1口公用一个中断向量,所有的P2口公用一个中断向量。所以在使用中断时,当进入中断后,还要判断到底是哪一个IO口产生的中断,判断方法可以是判断各个IO口的电平。 ???4,中断标志PxIFG需要软件清除,也可以用软件置位,从而用软件触发一个中断。 注意:在设置PxIESx时根据PxINx有可能会引起相应的PxIFGx置位(具体的情况见用户指南),所以在初始化完IO口中断以后,正式使用IO中断前要先将对应的PxIFGx清零。程序如下: void?IO_interrupt_init()?????//IO中断初始化函数 { ??P1REN?|=?BIT4+BIT5+BIT6+BIT7;?????//?pullup?内部上拉电阻使能 ??//使用中断时,使能内部的上拉电阻这样当该脚悬空是,电平不会跳变,防止悬空时电平跳变不停的触发中断 ??P1OUT?=?BIT4+BIT5+BIT6+BIT7;???//?当引脚上的上拉或下拉电阻使能时,PxOUT选择是上拉还是下来 ??????????//0:下拉,1:上拉 ? ??P1IE?|=?BIT4+BIT5+BIT6+BIT7;???????//?interrupt?enabled?P13中断使能 ??P1IES?|=?BIT4+BIT5+BIT6+BIT7;??????????//?Hi/lo?edge??下降沿中断 ??//P1IES?&=?~BIT3;?????????????????????????//上升沿触发中断 ??P1IFG?&=?~(BIT4+BIT5+BIT6+BIT7);?????????//中断标志位清零 ? } ? 5,PxOUT:如果引脚选择了内部的上拉或下拉电阻使能,则PxOUT设定电阻是上拉还是下拉,0:下拉,1:上拉 6,当IO口不用时,最好不要设为输入,且为浮动状态(这是IO口的默认状态),因为当输入为浮动时,输入电压有可能会在VIL和VIH之间,这样会产生击穿电流。所以不用的IO口可以设为输出状态,或设为输入状态但通过外围电路接至VCC或GND,或接一个上拉/下拉电阻。 7,当使用msp430g2553的IO口时要注意,因为g2553的IO口寄存器的操作,不像51,它不能单独针对某一位进行操作,必须对整个寄存器进行操作。所以就不像51,g2553不可以定义bit型的数据。所以在使用msp的IO口时要注意对需要位的操作,而不要影响其他无关的位,可以?用?|??&??^等按位操作的符号。在使用IO都控制其他外围模块时也要注意要使用的IO口的定义,可以用如下的定义方法: #define?CLR_RS?P2OUT&=~BIT0;????//RS?=?P2.0 #define?SET_RS?P2OUT|=BIT0; #define?CLR_RW?P2OUT&=~BIT1;?//RW?=?P2.1 #define?SET_RW?P2OUT|=BIT1; #define?CLR_EN?P2OUT&=~BIT2;?//EN?=?P2.2 #define?SET_EN?P2OUT|=BIT2; ? #define?DataPort????P1OUT ? 8,g2553的P27和P26脚分别接外部晶体的输出和输入脚XOUT和XIN,默认是自动设为了晶振管脚功能,但是当想把它们用为普通的IO时,也可以,设置对应的SEL设为普通的IO即可,如下: P2DIR?|=?BIT6+BIT7;????//把P26和P27配置为普通IO?并为输出脚??默认为晶振的输入和输出引脚?作为dac0832的 ????P2SEL?&=?~(BIT6+BIT7);???//cs和wr控制端 ????P2SEL2?&=?~(BIT6+BIT7); ? ? ? (二),时钟系统 ?????1,msp430能做到超低功耗,合理的时钟模块是功不可没的。但是功能强大的时钟模块设置起来也相对复杂一些。 ?????2,msp430的时钟源有: (1),外接低频晶振LFXT1CLK:低频模式接手表晶体32768Hz,高频模式450KHz~8MHz; (2),外接高速晶振XT2CLK:8MHz; (3),内部数字控制振荡器DCO:是一个可控的RC振荡器,频率在0~16MHz; (4),超低功耗低频振荡器VLO:不可控,4~20KHz?典型值为12KHz; ?????3,时钟模块:430的时钟模块有MCLK??SMCLK??ACLK?: (1),主系统时钟MCLK:提供给MSP430的CPU时钟。可以来自LFXT1CLK??XT2CLK??DCO??VLO可选,默认为DCO。 (2),子系统时钟SMCLK:?提供给高速外设。可以来自LFXT1CLK??XT2CLK??DCO??VLO可选,默认为DCO。 (3),辅助系统时钟ACLK:提供给低速外设。可来自LFXT1CLK??VLO。? ?????4,内部的振荡器DCO和VLO提供的时钟频率不是很精确,随外部环境变化较大。 DCO默认的频率大概为800KHz,但我用示波器观察的为1.086MHz左右,当DCO设置的过高时,用示波器可以看到波形不再是方波,而是类似于正弦波。DCO可以用CCS提供的宏定义进行相对比较精确的设置,如下: DCOCTL?=?CALDCO_12MHZ;???//DCO设为12MHz???这种方法设DCO频率比较精确,实际测得为12.08MHz左右?正弦波 BCSCTL1?=?CALBC1_12MHZ; 用这种方法可以设置1,8,12,16MHz 宏定义如下: #ifndef?__DisableCalData ? SFR_8BIT(CALDCO_16MHZ);??????????????????????? SFR_8BIT(CALBC1_16MHZ);??????????????????????? SFR_8BIT(CALDCO_12MHZ);??????????????????????? SFR_8BIT(CALBC1_12MHZ);??????????????????????? SFR_8BIT(CALDCO_8MHZ);???????????????????????? SFR_8BIT(CALBC1_8MHZ);???????????????????????? SFR_8BIT(CALDCO_1MHZ);???????????????????????? SFR_8BIT(CALBC1_1MHZ);???????????????????????? ? #endif? ? 5,使用超低功耗低频振荡器VLO可以很大程度地降低系统功耗,下面的例子是设置ACLK为VLO,MCLK为VLO的8分频: #include??<msp430g2553.h> ? //1延时 //#define?CPU_F?((double)16000000)//cpu?frequency16000000 #define?CPU_F?((double)1630)//cpu?frequency1630???//CPU的实际MCLK大约为13.05/8=1.63KHz #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)) ? ? void?main(void) { ??volatile?unsigned?int?i;??????????????????//?Volatile?to?prevent?removal ??WDTCTL?=?WDTPW?+?WDTHOLD;?????????????????//?Stop?watchdog?timer ? ??BCSCTL3?|=?LFXT1S_2;??????????????????????//?LFXT1?=?VLO??低频时钟选择为VLO?ACLK选为VLO ? ??IFG1?&=?~OFIFG;???????????????????????????//?Clear?OSCFault?flag??清除振荡器错误中断标志 ? ??__bis_SR_register(SCG1?+?SCG0);???????????//?Stop?DCO??SCG1禁止SMCLK??SCG0禁止DCO ? ??BCSCTL2?|=?SELM_3?+?DIVM_3;???????????????//?MCLK?=?LFXT1/8 ??//因为前面已经选择了LFXT1?=?VLO?所以MCLK选为VLO??8分频??所以CPU的MCLK大约为1.5KHz ? ??P1DIR?=?0xFF;?????????????????????????????//?All?P1.x?outputs ??P1OUT?=?0;????????????????????????????????//?All?P1.x?reset ??P2DIR?=?0xFF;?????????????????????????????//?All?P2.x?outputs ??P2OUT?=?0;????????????????????????????????//?All?P2.x?reset ? ??P1SEL?|=?BIT0+BIT4;????????????????//?P10?P14options??功能选择为外围模块 ??//p10输出ACLK,来自VLO,p14输出SMCLK,??因为禁止了SMCLK,所以P14脚无波形输出 ??//VLO典型值为12KHz??实际用示波器测得为:13.05KHz?左右波动 ??//所以CPU的实际MCLK大约为13.05/8=1.63KHz ? ? ??for?(;;) ??{ ????P1OUT?^=?BIT6;??????????//?P1.6?闪烁 ????delay_ms(1000); ??} } ? ??6,如上面的程序所示,其中的延迟函数用那种方法,使用系统的延迟周期函数__delay_cycles(int?n);?可以达到比较精确的延迟,如下: ? //more_ //1延时 //#define?CPU_F?((double)16000000)//cpu?frequency16000000 #define?CPU_F?((double)12000000)//cpu?frequency12000000 #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)) //2空函数 #define?nop()?_NOP(); ? ???7,系统上电后默认使用的是DCO时钟,DCO默认的频率大概为800KHz,但我用示波器观察的为1.086MHz左右,当DCO设置的过高时,用示波器可以看到波形不再是方波,而是类似于正弦波。 ? ? ? ?(三),定时器Timer_A ???1,MSP430g2553具有两个16位的定时器:Timer0_A???Timer1_A。分别具有三个捕捉/比较寄存器,具有输入捕捉,输出比较功能。可以产生定时中断,也可以产生PWM。 ???2,产生PWM,例子如下: ? #include?<msp430g2553.h> ? ?void?Timer_A0_1_init()??//TA0.1输出PWM { TACTL|=?TASSEL_1+MC_1;//ACLK,增计数 CCTL1=OUTMOD_7;//输出模式为复位/置位 CCR0=328;//时钟频率为32768HZ,100HZ //CCR1=164;//时钟频率为32768HZ,占空比CCR1/CCR0=50% CCR1=109;//占空比CCR1/CCR0=1/3??????????????????????????????TA0.1由P1.2?P1.6输出 } ? ?void?Timer_A1_2_init()????//TA1.2输出PWM { TA1CTL|=?TASSEL_1+MC_1;//ACLK,增计数 TA1CCTL2=OUTMOD_7;//输出模式为复位/置位,注意CCTL2要写为TA1CCTL2 ? TA1CCR0=164;//时钟频率为32768HZ,波形32768/CCR0=199HZ TA1CCR2=41;//占空比CCR2/CCR0=1/4,注意CCR2要写成TA1CCR2???????TA1.2由P2.4?P2.5输出 ? } ? ?void?Timer_A1_1_init()???//TA1.1输出PWM ?{ ?TA1CCTL1=OUTMOD_7; ?TA1CCR1=123;???//占空比CCR1/CCR0=3/4,注意CCR1要写成TA1CCR1???TA1.1由P2.1?P2.2输出 ?} ? ?void?IO_init() ?{ ?P1SEL|=BIT2+BIT6; ?P1DIR|=BIT2+BIT6;//P1.2?P1.6输出???TA0.1???OUT1 ? ?P2SEL|=BIT4+BIT5; ?P2DIR|=BIT4+BIT5;//P2.4?P2.5输出???TA1.2???OUT2 ? ?P2SEL|=BIT1+BIT2; ?P2DIR|=BIT1+BIT2;?//P2.1?P2.2输出??TA1.1???OUT1 ?} ? void?main(void)?{ WDTCTL=WDTPW+WDTHOLD; ? ????IO_init(); ? Timer_A0_1_init(); Timer_A1_2_init(); Timer_A1_1_init(); ? ? _BIS_SR(CPUOFF);??????????????????????????//?Enter?LPM0??进入低功耗模式0?SMCLK?ON,ACLK?ON } ? ??3,Timer_A的捕获/比较寄存器 TAR寄存器是Timer_A的16位的计数寄存器。TACCRx是Timer_A的捕获/比较寄存器,当为捕获模式时:当捕获发生时,把TAR的值装载到TACCRx中。当为比较模式时:TACCRx中装的是要与TAR寄存器相比较的值。 ???4,捕获模式 捕获外部输入的信号的上升沿或下降沿或上升沿下降沿都捕捉,当捕捉发生时,把TAR的值装载到TACCRx中,同时也可以进入中断,执行相应的操作。这样利用捕捉上升沿或下降沿就可以计算外部输入信号的周期,得出频率。利用捕捉上升沿和下降沿可以得出输入信号的高电平或低电平的持续时间。也可以算出占空比。下面是一个例子,是Timer_A捕获初始化的程序: void?timer_init()??????//使用Timer1_A时要特别注意各个寄存器的写法,因为Timer0_A的寄存器都简写了,所以在写 //Timer1_A的寄存器时,要特别注意与Timer0_A的不同 { P1SEL?|=?BIT2;????//选择P12作为捕捉的输入端子??Timer0_A ?//TACCTL1?|=CM_3+SCS+CAP+CCIE;??//上下沿都触发捕捉,用于测脉宽,同步模式、时能中断??CCI1A TACCTL1?|=CM_1+SCS+CAP+CCIE;??//上升沿触发捕捉,同步模式、时能中断??CCI1A ????TACTL?|=?TASSEL1+MC_2;??//选择SMCLK时钟作为计数时钟源,不分频???增计数模式不行,必须连续计数模式 ? ??P2SEL?|=?BIT1;????//选择P21作为捕捉的输入端子????Timer1_A ??//TA1CCTL1?|=CM_3+SCS+CAP+CCIE;??//上下沿都触发捕捉,用于测脉宽,同步模式、时能中断??CCI1A ??TA1CCTL1?|=CM_1+SCS+CAP+CCIE;??//上升沿触发捕捉,同步模式、时能中断??CCI1A ??TA1CTL?|=?TASSEL1+MC_2;??//选择SMCLK时钟作为计数时钟源,不分频???增计数模式不行,必须连续计数模式 ? } ? ? 相对应的中断函数如下: ? #pragma?vector=TIMER0_A1_VECTOR???//Timer0_A?CC1??的中断向量 __interrupt?void?Timer_A(void) { ? //?CCI0A?使用的捕捉比较寄存器是TA0CCR0,TA0CCR0单独分配给一个 ????//中断向量TIMER1_A0_VECTOR,所以进入中断后直接就是Timer0_A?CC0产生的中断,不用经过类似 ???//下面的方法判断中断源了??。 //Timer0_A?CC1-4,?TA0公用一个中断向量?TIMER0_A1_VECTOR,所以进入了中断后还要用下面 ????//的方法进行判断是哪一个中断源产生的中断 ??switch(TAIV)????//如果是Timer0_A?CC1产生的中断 ??{ ??case?2: ???{ ???flag=1; ???LPM1_EXIT;??????//退出低功耗模式 ??//?_BIC_SR_IRQ(LPM1_bits); ???//_bic_SR_register_on_exit(LPM1_bits); ???break; ???} ??case?4:?break; ??case?10:break; ??} } ? ? #pragma?vector=TIMER1_A1_VECTOR??????//Timer1_A?CC1??的中断向量 __interrupt?void?Timer_A1(void) { ? //?P1OUT|=BIT0;??//led调试用的 //?LPM1_EXIT;??????//退出低功耗模式??因为使用的是CCI0A?使用的捕捉比较寄存器是TA1CCR0,TA1CCR0单独分配给一个 ????????????????//中断向量TIMER1_A0_VECTOR,所以进入中断后直接就是Timer1_A?CC0产生的中断,不用经过类似 ???????????????//下面注释掉的方法判断??。 ???????????????//而Timer1_A?CC1-4,?TA1则公用一个中断向量?TIMER1_A1_VECTOR,所以进入了中断后还要用下面 ???????//的方法进行判断是哪一个中断源产生的中断 ??switch(TA1IV)????//如果是Timer1_A?CC1产生的中断 ??{ ??case?2: ???{ ???flag=2; ???LPM1_EXIT;??????//退出低功耗模式 ? ??//?_BIC_SR_IRQ(LPM1_bits); ???//_bic_SR_register_on_exit(LPM1_bits); ???break; ???} ??case?4:break; ??case?10:break; ??} } ? //如果要测量更低频率的信号的话,可以在中断中判断溢出中断发生的次数,这样就可以得到溢出的次数,从而可以测量更 //低频率的信号 ? ??5,Timer_A的计数模式 计数模式有:增计数模式,连续计数模式和增减计数模式。具体的各个模式的详解,参见用户指南。 ???6,定时器的定时中断 在使用定时器的定时中断时,要注意定时器计数模式的选择。在使用中断时,要注意中断向量的使用和中断源的判断,下面就举一个例子,注释的也较详细: #include?<msp430g2553.h> ? unsigned?int?t=0; ? void?main(void) { ??WDTCTL?=?WDTPW?+?WDTHOLD;?????????????????//?Stop?WDT ??P1DIR?|=?0x01;????????????????????????????//?P1.0?output ? ??CCTL0?=?CCIE;???//?CCTLx是捕获/比较控制寄存器???interrupt?enabled??CCIE=0x0010??时能定时器A中断 ? ??CCR0?=?50000;???//捕获/比较寄存器???设置计数器CCR0的初值??16位寄存器,最大值为65535 ????????????????//默认SMCLK使用的是DCO,默认的DCO大约为800KHz,而CCR0=50000,所以中断产生的频率大约为16Hz ??TACTL?=?TASSEL_2?+?MC_2;??????????????????//?SMCLK,?contmode??连续计数模式从0计到0FFFFh ??//TACTL?=?TASSEL_2?+?MC_1;??????????????????//?SMCLK,?upmode??增计数模式从0计到CCR0 ? ??_BIS_SR(LPM0_bits?+?GIE);?????????????????//?Enter?LPM0?w/?interrupt??进入低功耗模式0,允许中断 } ? //?Timer?A0?interrupt?service?routine #pragma?vector=TIMER0_A0_VECTOR __interrupt?void?Timer_A?(void)????//CCIFG中断被响应后,该标志位自动清零 ? { ??//P1OUT?^=?0x01;????????????????????????????//?Toggle?P1.0 t++; if(t==5) { P1OUT?^=?BIT0;???????????//?Toggle?P1.0 t=0; } ? ??CCR0?+=?50000;????????????????????????????//?Add?Offset?to?CCR0??增加CCR0偏移 ? ??? ??//定时器总是从0开始往上计数,一直到计满再从0开始,在连续计数模式下,当定时器的值等于CCR0时,产生中断 ??//在中断中对CCR0增加50000,这样的话定时器从当前值到下一时刻再次等于CCR0时的间隔为50000,恒定 ??//这样产生中断的时间间隔就相等了 ?//所以在连续计数模式下,要想使中断的时间间隔一定,就要有CCR0?+=?n;这句话 ??????????????????????????????????????????????//在中断中CCR0不需要从新赋值,区别于51 } ? 中断的使用注意情况:还是把举个例子吧: #include?<msp430g2553.h> ? void?main(void) { ??WDTCTL?=?WDTPW?+?WDTHOLD;?????????????????//?Stop?WDT ??P1DIR?|=?0x01;????????????????????????????//?P1.0?output ??TACTL?=?TASSEL_2?+?MC_2?+?TAIE;???????????//?SMCLK,?contmode,?interrupt??TAIE允许定时器溢出中断 ? ??_BIS_SR(LPM0_bits?+?GIE);?????????????????//?Enter?LPM0?w/?interrupt??GIE允许中断 } ? //?Timer_A3?Interrupt?Vector?(TA0IV)?handler #pragma?vector=TIMER0_A1_VECTOR __interrupt?void?Timer_A(void) { ?switch(?TA0IV?)????//TAIV中断向量寄存器??用于 ?{ ???case??2:?break;??????????????????????????//?CCR1?not?used???捕获/比较器1 ???case??4:?break;??????????????????????????//?CCR2?not?used????捕获/比较器2 ???case?10:?P1OUT?^=?0x01;??????????????????//?overflow??定时器溢出 ????????????break; ?} } ? ? ? ??7,注意:定时器Timer0_A的时钟可以选择为外接时钟输入TACLK(P10),这样当外接一个信号时,定时器Timer0_A就相当于一个计数器使用。这样就可以用Timer0_A接外接信号,Timer1_A接标准的时钟如32768Hz的晶振,就可以实现等精度测频了。其实Timer1_A的时钟也可以外接的,但是在g2553中没有这个外接管脚(P37),所以就只能选择正常的时钟了。 Timer0_A的外接时钟输入TACLK(P10)的设置如下:下面是我实现等精度测频时,两个定时器的初始化程序: void?timer0_init() { TACTL?|=?TASSEL_0+MC_2+TACLR;??//选择TACLK时钟作为计数时钟源,不分频???必须连续计数模式 ? P1SEL?|=?BIT0;???//P10为Timer0_A的时钟TACLK输入,接外部待测信号,这样Timer0_A就当作计数器用 } //Timer1_A采用ACLK作为时钟源计数,这样ACLK就相当于是标准信号,这样两个定时器相当于都工作在计数器方式, //ACLK?32768Hz作为标准信号,这样可以实现等精度测频 void?timer1_init() { ? TA1CCTL0?=?CCIE; TA1CCR0?=?32768;????//1s定时 ? TA1CTL?|=?TASSEL_1+MC_2+TACLR;??//选择ACLK时钟作为计数时钟源,不分频???必须连续计数模式 ? } 8,用定时器和比较器可以实现DAC ???使用定时器也可以实现串口通信 ?

      下载次数 15次 资源类型 其它 上传时间 2017-03-31

    2. 蓝桥杯单片机真题

      标签:蓝桥杯 单片机

      电风扇模拟控制系统设计 一、功能简述: 电风扇模拟控制系统能模拟电风扇工作,主要由电机控制电路、电机过热检测与保护电路、定时和状态显示电路等组成。 二、设计任务: 1.用4位数码管实时显示电风扇的工作状态,最高位显示风类:“自然风” 显示“ 1”、 “常风” 显示“2”、“睡眠风” 显示“3”。后3位显示定时时间:动态倒计时显示剩余的定时时间,无定时显示“000”。 2.设计 “自然风”、 “常风”和“睡眠风” 三个风类键用于设置风类; 设计一个“定时”键,用于定时时间长短设置; 设计一个“摇头” 键用于控制电机摇头。 3.设计过热检测与保护电路,若电风扇电机过热,则电机停止转动,电机冷却后电机又恢复转动。 三、设计要求 1.必须充分利用给定套装元件(内附元件,材料清单表)进行设计。 2.用一个直流小电机模拟电风扇电机,按下相应的风类键,电机工作在相应状态:“自然风”运行时PWM的占空比为1:3;“睡眠风”运行时PWM的占空比为1:5;“常风”运行时PWM的占空比为3:1。 3.每按一次“定时”键,定时时间增加10秒钟,工作过程如下:(图略) 4. 用另一个直流小电机模拟风扇摇头机构,按下“摇头” 键,“摇头”电机先正转30ms,再反转30ms,如次往复。 6.过热检测与保护电路不用传感器,用信号源产生的正弦波信号代替传感器“感应”出的信号,若信号幅度大于10mV,则电机停止转动。 四、上交电子文档 1.电风扇模拟控制系统原理示意图; 2.电风扇模拟控制系统电路原理图(用PROTEL软件); 3.电风扇模拟控制系统程序流程图; 4.电风扇模拟控制系统源程序。 ▲ 上交电子文档必须以选手比赛编号命名,不得使用实名,否则比赛成绩记为0分。 假如比赛编号为200917234,则四个电子文档依次命名为:200917234示意图.BMP;200917234原理图;200917234流程图.BMP;200917234源程序.TXT 参考电路 ============================================================= 代码说明: 1. 代码中将P2口作为LED的8个段的输出口,PO口作为位控,采用共阴LED数码管。由于89S52的I/O口驱动比较小,所以亮度不太高。可以通过调节限流电阻提高亮度。 2. 实际板上有一片1413驱动,可以作为LED数码管显示的位驱动,这样亮度就没有问题了。 3. 代码中尽量保证RAM的前128B(直接寻址)全部给用户变量使用,把堆栈放在后128B的空间,固定数据的数组定义在FLASH空间(见代码中有CODE声明的数组变量定义) 4. 外围的马达的驱动电路、马达、继电器、温度输入检测没有接,通过模拟方式验证和调试 5. PWM的输出直接控制板上的一个LED,不同占空比时,LED的亮度变化代表了转速的不同。实际如果有马达的话,只要根据实际情况,改变PWM的频率就可以了。 6. 摆动马达控制也可以使用2个LED显示控制I/O的输出情况 7. 采用一个I/O输入“1”或“0”表示温度的超过或正常。 参考代码 //================================================================== #include <Reg52.h> #include <intrins.h> //******************************************** // I/O port design //******************************************** //输入定义 #define Key_null 0xff #define Key_f 0xfe #define Key_m 0xfd #define Key_t 0xfb //控制输出/输入 sbit m_out = P3^6; sbit pwm_out = P3^7; sbit err_in = P1^3; //函数声明 void led_display(void); //====== //PWM 电机输出控制 (timer0 中断) code unsigned int pwm_m1[3] = {62536,56536,63536}; code unsigned int pwm_m2[3] = {56536,62536,55536}; unsigned char th01_new,tl01_new; unsigned char th02_new,tl02_new; bit pwm_state; void timer1(void) interrupt 1 //定时0中断 { if(pwm_state) { TL0 = tl01_new; TH0 = th01_new; pwm_out = 0; } else { TL0 = tl02_new; TH0 = th02_new; pwm_out = 1; } pwm_state = ~pwm_state; } bit key_time_ok,time_1s_ok; unsigned char key_time,time_1s; void timer0(void) interrupt 3 //定时1中断 { TL1 = 0x78; // THTL=0xec78 = 65536 - 5000(5ms) TH1 = 0xec; led_display(); // LED动态扫描 if (++key_time >= 4) { key_time = 0; key_time_ok = 1; //10ms到 if(++time_1s >= 50) { time_1s = 0; time_1s_ok = 1; //1秒到 } } } //====== //LED数码管扫描显示驱动 unsigned char dis_buff[4]; code unsigned char led_7[13]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40,0x79}; code unsigned char position[4]= {0xfe,0xfd,0xfb,0xf7}; void led_display(void) // 4位LED数码管动态扫描函数,5ms执行一次 { static unsigned char posit; P0 = 0xff; // 关全部显示 P2 = led_7[dis_buff[posit]]; // 输出一位段码 P0 = position[posit]; // 显示其中一位 if(++posit >= 4) posit = 0; } //======================= //按键扫描底层接口 unsigned char read_key(void) { static unsigned char key_press_old = Key_null,key_state = 0 ; unsigned char key_value= Key_null,key_press; key_press = P1; switch (key_state) { case 0: if(key_press != Key_null) key_state = 1; break; case 1: if (key_press != key_press_old) { key_state = 0; } else { if (key_press == Key_f) key_value = Key_f; if (key_press == Key_m) key_value = Key_m; if (key_press == Key_t) key_value = Key_t; key_state = 2; } break; case 2: if (key_press == Key_null) key_state = 0; break; } key_press_old = key_press; return key_value; } //============================================================================= // 主程序 //============================================================================= void main(void) { bit delay_time_ok = 0,m_type_ok = 0, move_on = 0; unsigned char f_type = 1,time_type = 0,delay_time = 0,move_time = 0,key; EA = 0; //关闭全局中断 SP = 0x80; //将堆栈空间定义到RAM后128B的空间,让出前128B给变量 P2 = 0x00; P3 = 0x00; P0 = 0xff; P1 = 0xff; //Configure Timer0,Mode=1,Interrupt=ENABLED,Clock Source=INTERNAL,Enable Gating Control=DISABLED TMOD &= 0XF0; /* clear Timer 0 */ TMOD |= 0X01; TL0 = 0x78; TH0 = 0xec; ET0 = 1; /* IE.1*/ TR0 = 1; /* TCON.4 start timer */ //Configure Timer1,Mode=1,Interrupt=ENABLED,Clock Source=INTERNAL,Enable Gating Control=DISABLED TMOD &= 0X0F; /* clear Timer 1 control */ TMOD |= 0X10; TL1 = 0X78; // THTL=0xec78 = 65536 - 5000(5ms) TH1 = 0Xec; ET1 = 1; /* ET0 is IE.3 */ TR1 = 1; /* TCON.6 start timer */ dis_buff[3] = f_type; dis_buff[2] = 10; dis_buff[1] = 0; dis_buff[0] = 0; th01_new = pwm_m1[f_type-1] >> 8; tl01_new = pwm_m1[f_type-1]; th02_new = pwm_m2[f_type-1] >> 8; tl02_new = pwm_m2[f_type-1]; EA = 1; //打开全局中断 while(1) { if (err_in) { if(key_time_ok) { key_time_ok = 0; key = read_key(); if (key != Key_null) { if (key == Key_f) { if (++f_type >= 4) f_type = 1; th01_new = pwm_m1[f_type-1] >> 8; tl01_new = pwm_m1[f_type-1]; th02_new = pwm_m2[f_type-1] >> 8; tl02_new = pwm_m2[f_type-1]; dis_buff[3] = f_type; } else if(key == Key_t) { if (++time_type >= 7) { time_type = 0; delay_time_ok = 0; delay_time = 0; } else { delay_time_ok = 1; delay_time = time_type * 10; } } else if(key == Key_m) { m_type_ok = ~m_type_ok; } } } if (time_1s_ok) { time_1s_ok = 0; if(delay_time) delay_time-- ; dis_buff[1] = delay_time / 10; dis_buff[0] = delay_time % 10; if (m_type_ok) { if (++move_time >= 3) { move_time = 0; move_on = ~move_on; } } } if (delay_time_ok) dis_buff[2] = 11; else dis_buff[2] = 10; if (delay_time_ok && (delay_time == 0)) { ET0 = 0; pwm_out = 1; } else { ET0 = 1; } if (m_type_ok) m_out = move_on; } else { ET0 = 0; pwm_out = 1; dis_buff[2] = 12; } } }

      下载次数 4次 资源类型 应用文档 上传时间 2017-03-31

最近访客

< 1/1 >

统计信息

已有3人来访过

  • 芯积分:2
  • 好友:--
  • 主题:1
  • 回复:9

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言