基于MSP430自行车智能测速系统设计具体程序
时间: 2023-06-12 21:04:39 浏览: 138
以下是基于MSP430的自行车智能测速系统设计的具体程序,包括硬件配置和软件编程:
硬件配置:
- MSP430F5529 LaunchPad开发板
- 蓝牙模块HC-05
- 三个光电传感器
- 一个LCD1602液晶显示屏
电路连接:
- 将三个光电传感器分别连接到MSP430的P1.0、P1.1和P1.2引脚,通过3.3kΩ电阻将每个传感器输出引脚连接到MSP430的P1.3、P1.4和P1.5引脚。
- 将LCD1602液晶显示屏的RS、RW和E引脚连接到MSP430的P2.0、P2.1和P2.2引脚,将液晶显示屏的D4~D7引脚连接到MSP430的P2.4~P2.7引脚。
- 将蓝牙模块HC-05的TXD引脚连接到MSP430的P3.3引脚,将蓝牙模块的RXD引脚连接到MSP430的P3.4引脚。
软件编程:
```c
#include <msp430.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lcd1602.h"
#define SENSOR1 BIT0
#define SENSOR2 BIT1
#define SENSOR3 BIT2
#define SENSOR_OUT P1IN
#define SENSOR_DIR P1DIR
#define SENSOR_REN P1REN
#define SENSOR_SEL P1SEL
#define SENSOR_IE P1IE
#define SENSOR_IES P1IES
#define SENSOR_IFG P1IFG
volatile unsigned int count; // 计数器
volatile unsigned int speed; // 速度
volatile unsigned int rpm; // 转速
volatile unsigned int distance; // 距离
volatile unsigned int time; // 时间
volatile unsigned char buffer[16]; // 用于LCD显示的缓冲区
volatile unsigned char display_mode; // 显示模式
volatile unsigned char is_display_on; // 是否显示
void init_msp430()
{
WDTCTL = WDTPW | WDTHOLD; // 关闭看门狗
P1DIR = 0x00; // P1设为输入
P1OUT = 0x00; // P1输出为0
P2DIR |= 0xFC; // P2的低6位设为输出
P2OUT &= 0x03; // P2的低6位输出为0
P3SEL |= 0x30; // P3.4和P3.3设为UART模式
P3DIR |= 0x10; // P3.4设为输出
TA0CTL = TASSEL_2 + ID_0 + MC_1 + TACLR; // 设置Timer A0为SMCLK,不分频,增计数模式,清空计数器
TA0CCR0 = 32767; // 设定计数器上限
TA0CCTL0 = CCIE; // 允许CCR0中断
SENSOR_REN |= SENSOR1 + SENSOR2 + SENSOR3; // 使能内部上拉电阻
SENSOR_DIR &= ~(SENSOR1 + SENSOR2 + SENSOR3); // P1.0~P1.2设为输入
SENSOR_SEL &= ~(SENSOR1 + SENSOR2 + SENSOR3); // P1.0~P1.2设为普通IO功能
SENSOR_IES = SENSOR1 + SENSOR2 + SENSOR3; // 设置P1.0~P1.2下降沿中断
SENSOR_IFG &= ~(SENSOR1 + SENSOR2 + SENSOR3); // 清空中断标志位
SENSOR_IE |= SENSOR1 + SENSOR2 + SENSOR3; // 使能P1.0~P1.2中断
_BIS_SR(GIE); // 允许全局中断
}
void update_speed()
{
rpm = count * 120; // 计算转速
speed = rpm * 2; // 计算速度
distance += speed / 3600; // 计算距离
time++; // 增加时间
count = 0; // 重置计数器
}
void display_speed()
{
switch (display_mode)
{
case 0:
sprintf(buffer, "Speed:%4d km/h", speed);
break;
case 1:
sprintf(buffer, "RPM:%4d", rpm);
break;
case 2:
sprintf(buffer, "Distance:%4d km", distance);
break;
case 3:
sprintf(buffer, "Time:%02d:%02d:%02d", time / 3600, (time % 3600) / 60, time % 60);
break;
}
lcd1602_clear();
lcd1602_write_string(buffer);
}
void send_data(unsigned char data)
{
while (!(UCA1IFG & UCTXIFG)); // 等待发送缓冲区为空
UCA1TXBUF = data; // 发送数据
}
void send_speed()
{
sprintf(buffer, "Speed:%4d km/h", speed);
send_data(strlen(buffer)); // 发送字符串长度
for (int i = 0; i < strlen(buffer); i++)
{
send_data(buffer[i]); // 发送字符串
}
}
void send_rpm()
{
sprintf(buffer, "RPM:%4d", rpm);
send_data(strlen(buffer)); // 发送字符串长度
for (int i = 0; i < strlen(buffer); i++)
{
send_data(buffer[i]); // 发送字符串
}
}
void send_distance()
{
sprintf(buffer, "Distance:%4d km", distance);
send_data(strlen(buffer)); // 发送字符串长度
for (int i = 0; i < strlen(buffer); i++)
{
send_data(buffer[i]); // 发送字符串
}
}
void send_time()
{
sprintf(buffer, "Time:%02d:%02d:%02d", time / 3600, (time % 3600) / 60, time % 60);
send_data(strlen(buffer)); // 发送字符串长度
for (int i = 0; i < strlen(buffer); i++)
{
send_data(buffer[i]); // 发送字符串
}
}
void main()
{
init_msp430();
lcd1602_init();
is_display_on = 1;
display_mode = 0;
while (1)
{
if (is_display_on)
{
display_speed();
}
__delay_cycles(1000);
}
}
#pragma vector = PORT1_VECTOR
__interrupt void port1_isr()
{
if (SENSOR_OUT & SENSOR1)
{
count++;
}
if (SENSOR_OUT & SENSOR2)
{
count++;
}
if (SENSOR_OUT & SENSOR3)
{
count++;
}
SENSOR_IFG &= ~(SENSOR1 + SENSOR2 + SENSOR3); // 清空中断标志位
}
#pragma vector = TIMER0_A0_VECTOR
__interrupt void timer0_a0_isr()
{
update_speed();
if (is_display_on)
{
switch (display_mode)
{
case 0:
break;
case 1:
lcd1602_clear();
lcd1602_write_string("RPM");
lcd1602_set_cursor(0, 1);
sprintf(buffer, "%4d", rpm);
lcd1602_write_string(buffer);
break;
case 2:
lcd1602_clear();
lcd1602_write_string("Distance");
lcd1602_set_cursor(0, 1);
sprintf(buffer, "%4d km", distance);
lcd1602_write_string(buffer);
break;
case 3:
lcd1602_clear();
lcd1602_write_string("Time");
lcd1602_set_cursor(0, 1);
sprintf(buffer, "%02d:%02d:%02d", time / 3600, (time % 3600) / 60, time % 60);
lcd1602_write_string(buffer);
break;
}
}
}
#pragma vector = USCI_A1_VECTOR
__interrupt void usci_a1_isr()
{
switch (UCA1RXBUF)
{
case 's':
send_speed();
break;
case 'r':
send_rpm();
break;
case 'd':
send_distance();
break;
case 't':
send_time();
break;
case '0':
display_mode = 0;
break;
case '1':
display_mode = 1;
break;
case '2':
display_mode = 2;
break;
case '3':
display_mode = 3;
break;
case 'o':
is_display_on = 1;
break;
case 'f':
is_display_on = 0;
break;
}
}
```
这个程序包含了四个中断服务程序:
1. P1中断服务程序:当光电传感器的输出信号变为低电平时,计数器加1。
2. Timer A0中断服务程序:每1秒钟更新一次速度、转速、距离和时间,并根据当前的显示模式在LCD显示屏上显示相应的信息。
3. USCI A1中断服务程序:当从蓝牙模块接收到数据时,根据不同的命令发送速度、转速、距离、时间或改变显示模式或是否显示的设置。
4. 全局中断服务程序:通过 BIS_SR(GIE) 允许全局中断。
整个程序的基本思路是,在P1中断服务程序中,当光电传感器的输出信号变为低电平时,计数器加1。在Timer A0中断服务程序中,每1秒钟更新一次速度、转速、距离和时间,并根据当前的显示模式在LCD显示屏上显示相应的信息。在USCI A1中断服务程序中,当从蓝牙模块接收到数据时,根据不同的命令发送速度、转速、距离、时间或改变显示模式或是否显示的设置。
阅读全文