基于MSP430单片机的出租车计费系统设计与开发,请编写代码,实现以下功能: (1) 用一个按键控制汽车前进档位编号,根据不同档位体现汽车行驶速度,该档位可以在数码管显示; (2) 根据档位值、以及运行时间,实时显示里程值变化; (3) 有暂停功能,当暂停之后,电机运转期间,里程停止累积; (4) 具有里程清零操作
时间: 2023-12-11 08:05:05 浏览: 177
一种基于MSP430单片机的时钟系统设计与实现
由于篇幅有限,这里只提供基本的代码框架,具体实现需要根据硬件情况进行调整。
```C
#include <msp430g2553.h>
#define FREQ 1000000 // MSP430时钟频率
#define KEY BIT3 // 按键引脚
#define MOTOR BIT4 // 电机引脚
#define LED BIT6 // LED引脚
#define DIG1 BIT0 // 数码管第一位引脚
#define DIG2 BIT1 // 数码管第二位引脚
#define DIG3 BIT2 // 数码管第三位引脚
#define DIG4 BIT3 // 数码管第四位引脚
#define MAX_SPEED 3 // 最大档位
#define SPEED_DELAY 200 // 不同档位之间的延迟
volatile unsigned int speed = 0; // 当前档位
volatile unsigned int mileage = 0; // 当前里程
volatile unsigned int paused = 0; // 是否暂停
void init(); // 初始化函数
void update_speed(); // 更新档位和数码管显示
void update_mileage(); // 更新里程和数码管显示
void clear_mileage(); // 里程清零操作
void main()
{
init(); // 初始化
while(1)
{
if(!(P1IN & KEY)) // 如果按键被按下
{
__delay_cycles(10000); // 延迟一段时间防止抖动
if(!(P1IN & KEY)) // 如果按键仍被按下
{
if(speed == MAX_SPEED) // 如果已经是最大档位则回到第一档
speed = 1;
else
speed++; // 否则档位+1
update_speed(); // 更新档位和数码管显示
}
while(!(P1IN & KEY)); // 等待按键释放
}
if(!paused) // 如果没有暂停
{
P1OUT |= MOTOR; // 电机转动
__delay_cycles(SPEED_DELAY * speed); // 根据档位延迟
mileage += speed; // 更新里程
update_mileage(); // 更新里程和数码管显示
}
}
}
void init()
{
WDTCTL = WDTPW + WDTHOLD; // 停用看门狗定时器
BCSCTL1 = CALBC1_1MHZ; // 设置时钟频率为1MHz
DCOCTL = CALDCO_1MHZ;
P1DIR |= MOTOR + LED + DIG1 + DIG2 + DIG3 + DIG4; // 设置引脚为输出
P1OUT &= ~(MOTOR + LED + DIG1 + DIG2 + DIG3 + DIG4); // 初始化引脚状态
TACTL = TASSEL_2 + MC_1 + ID_0; // 设置定时器A的时钟源为SMCLK,计数模式为增加计数器,时钟分频为1
TACCR0 = FREQ - 1; // 设置计数器最大值为时钟周期
TACCTL0 = CCIE; // 允许定时器A的中断
__enable_interrupt(); // 允许中断
}
void update_speed()
{
switch(speed)
{
case 1:
P1OUT &= ~(DIG1 + DIG2 + DIG3 + DIG4); // 关闭所有数码管
P1OUT |= DIG1; // 第一位数码管显示1
break;
case 2:
P1OUT &= ~(DIG1 + DIG2 + DIG3 + DIG4); // 关闭所有数码管
P1OUT |= DIG2; // 第二位数码管显示2
break;
case 3:
P1OUT &= ~(DIG1 + DIG2 + DIG3 + DIG4); // 关闭所有数码管
P1OUT |= DIG3; // 第三位数码管显示3
break;
}
}
void update_mileage()
{
unsigned int temp = mileage;
unsigned char digit[4] = {0}; // 里程数码管显示
for(int i = 0; i < 4; i++)
{
digit[i] = temp % 10; // 取出最低位
temp /= 10; // 去除最低位
}
if(digit[0] != 0) // 如果最高位不为0
{
P1OUT &= ~(DIG1 + DIG2 + DIG3 + DIG4); // 关闭所有数码管
P1OUT |= DIG4; // 第四位数码管显示最低位
P1OUT |= digit[0] << 4; // 数码管显示
__delay_cycles(1000); // 延迟一段时间
}
if(digit[1] != 0 || digit[0] != 0) // 如果前两位不全为0
{
P1OUT &= ~(DIG1 + DIG2 + DIG3 + DIG4); // 关闭所有数码管
P1OUT |= DIG3; // 第三位数码管显示次高位
P1OUT |= digit[1] << 4; // 数码管显示
__delay_cycles(1000); // 延迟一段时间
}
if(digit[2] != 0 || digit[1] != 0 || digit[0] != 0) // 如果前三位不全为0
{
P1OUT &= ~(DIG1 + DIG2 + DIG3 + DIG4); // 关闭所有数码管
P1OUT |= DIG2; // 第二位数码管显示中间位
P1OUT |= digit[2] << 4; // 数码管显示
__delay_cycles(1000); // 延迟一段时间
}
P1OUT &= ~(DIG1 + DIG2 + DIG3 + DIG4); // 关闭所有数码管
P1OUT |= DIG1; // 第一位数码管显示最高位
P1OUT |= digit[3] << 4; // 数码管显示
__delay_cycles(1000); // 延迟一段时间
}
void clear_mileage()
{
mileage = 0; // 里程清零
update_mileage(); // 更新里程和数码管显示
}
#pragma vector = TIMER0_A0_VECTOR // 定时器A的中断服务函数
__interrupt void Timer_A()
{
P1OUT ^= LED; // LED闪烁
}
```
阅读全文