一边学习,一边记录,有踩坑,有试错,有经验。此前完全不会电。
配置阶段就不赘述了,真的,Ti的开发者手册就很明白。比别的开发板配置简单不止一点点(笔者同时还在学STM32)
1.点亮LED灯
成功,耗时几分钟。
LED2
#include <msp430.h>
/**
* main.c
*/
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
//P4.7为输出
P4DIR=0x80; //0x80=1000 0000,查看数据手册可知,P4.7为输出,P4其他脚为输入
//P4.7输出高电平
P4OUT=0x80; //0x80=1000 0000,查看数据手册可知,P4.7为输出高电平,P4其他脚为下拉输入
return 0;
}
把P4改为P1,80改01
附代码图为LED1,2一起亮.
看视频,了解看门狗是什么。
队友来了,我不是一个人了。直接开搞超声波模块。
还是要再了解一波MSP430,不然程序也不会写呀。又去看视频教程了
从液晶显示屏开始练手吧!
#include <msp430.h>
#define RS_CLR P1OUT &= ~BIT2;
#define RS_SET P1OUT |= BIT2;
#define RW_CLR P1OUT &= ~BIT3;
#define RW_SET P1OUT |= BIT3;
#define EN_CLR P1OUT &= ~BIT4;
#define EN_SET P1OUT |= BIT4;
#define DataPort P3OUT
void LCD1602_Port_init()
{
P3SEL |= 0x00;
P3DIR |= 0xFF;
P1DIR |= BIT2 + BIT3 + BIT4; // 控制口设置为输出模式
}
void LCD1602_write_com(unsigned char com)
{
RS_CLR;
RW_CLR;
DataPort = com; // 命令写入端口
delay_ms(5);
EN_SET;
delay_ms(5);
EN_CLR;
}
void LCD_init(void)
{
EN_CLR;
LCD1602_write_com(0x38); // 显示模式设置, 8位数据显示,双行
delay_ms(5);
// LCD1602_write_com(0x08); // 显示关闭
// delay_ms(5);
LCD1602_write_com(0x0C); // 显示开及光标设置
delay_ms(5);
LCD1602_write_com(0x06); // 显示光标移动设置
delay_ms(5);
LCD1602_write_com(0x01); // 显示清屏
delay_ms(5);
}
int main(void)
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW | WDTHOLD;
LCD1602_Port_init();
LCD1602_init();
LCD1602_write_com(0x01);
LCD1602_write_com(0x80);
LCD1602_write_data('6');
LCD1602_write_data(0x39);
LCD1602_write_com(0xc0);
LCD1602_write_data('7');
LCD1602_write_data(0x32);
return 0;
}
企图接入1602显示屏,不行。但是不认为是接线错误,应该是显示屏被烧坏了。
#include <msp430.h>
#define CPU_F ((double)8000000)
#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))
#define DataDir P3DIR
#define DataPort P3OUT
//#define Busy 0x80
//#define CtrlDir P1DIR
#define RS_CLR P1OUT&=~BIT3; //RS = P1.3
#define RS_SET P1OUT|=BIT3;
#define RW_CLR P1OUT&=~BIT4; //RW = P1.4
#define RW_SET P1OUT|=BIT4;
#define EN_CLR P1OUT&=~BIT5; //EN = P1.5
#define EN_SET P1OUT|=BIT5;
/*------------------------------------------------
判忙函数
------------------------------------------------*/
int LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
delay_ms(5);
EN_SET;
return (DataPort & 0x80);
}
void Port_init()
{
P1DIR |= BIT3+BIT4+BIT5;
DataDir = 0xFF;
}
/*------------------------------------------------
写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{
// while(LCD_Check_Busy()); //忙则等待
delay_ms(5);
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
delay_ms(5);
EN_CLR;
}
/*------------------------------------------------
写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data) //ok
{
//while(LCD_Check_Busy()); //忙则等待
delay_ms(5);
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
delay_ms(5);
EN_CLR;
}
/*------------------------------------------------
清屏函数
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
delay_ms(5);
}
/*------------------------------------------------
写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) //ok
{
if (y == 0)
{
LCD_Write_Com(0x80 + x); //表示第一行
}
else
{
LCD_Write_Com(0xC0 + x); //表示第二行
}
while (*s)
{
LCD_Write_Data( *s);
s++;
}
}
/*------------------------------------------------
写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) //OK
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data(Data);
}
/*------------------------------------------------
初始化函数
------------------------------------------------*/
void LCD_Init(void) //ok
{
LCD_Write_Com(0x38); /*显示模式设置*/
delay_ms(5);
LCD_Write_Com(0x38);
delay_ms(5);
LCD_Write_Com(0x38);
delay_ms(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*显示关闭*/
LCD_Write_Com(0x01); /*显示清屏*/
LCD_Write_Com(0x06); /*显示光标移动设置*/
delay_ms(5);
LCD_Write_Com(0x0C); /*显示开及光标设置*/
}
/*------------------------------------------------
主函数
------------------------------------------------*/
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
Port_init();
delay_ms(10);
LCD_Init();
LCD_Clear();//清屏
while (1)
{
LCD_Write_Char(7,0,'o');
LCD_Write_Char(8,0,'k');
LCD_Write_String(0,1,"make it possible");
while(1);
}
}
下面是pid调速测试,是失败的?加入时间循环去判别,时钟对不上。
#include <msp430.h>
#define ENCODER_A_PIN BIT4
#define ENCODER_B_PIN BIT5
#define ENCODER_A_INT TA0CCTL1
#define ENCODER_B_INT TA0CCTL2
#define MOTOR_A_PIN BIT2
#define MOTOR_B_PIN BIT3
#define TARGET_SPEED 1000
#define TARGET_SPEED1 5000
#define Kp 0.1
#define Ki 2.5
#define Kd 0.5
volatile int encoderCount = 0;
volatile int motorSpeed = 0;
double error = 0;
double previousError = 0;
double integral = 0;
double derivative = 0;
void initPWM()
{
// 初始化定时器和PWM模块
// 设置定时器的计数模式和频率
// 设置PWM模块的输出引脚和占空比
}
void initEncoder()
{
// 配置引脚为输入模式
P1DIR &= ~(ENCODER_A_PIN | ENCODER_B_PIN);
P1REN |= ENCODER_A_PIN | ENCODER_B_PIN;
P1OUT |= ENCODER_A_PIN | ENCODER_B_PIN;
P1IE |= ENCODER_A_PIN | ENCODER_B_PIN;
P1IES |= ENCODER_A_PIN | ENCODER_B_PIN;
P1IFG &= ~(ENCODER_A_PIN | ENCODER_B_PIN);
}
void initMotor()
{
// 配置引脚为输出模式
P1DIR |= MOTOR_A_PIN | MOTOR_B_PIN;
P1OUT &= ~(MOTOR_A_PIN | MOTOR_B_PIN);
}
void initPID()
{
// 初始化PID控制器的参数
error = 0;
previousError = 0;
integral = 0;
derivative = 0;
}
void setMotorSpeed(int speed)
{
// 设置电机的速度
motorSpeed = speed;
// 根据速度和PID控制器的输出值来控制电机引脚的状态
if (motorSpeed > 0)
{
P1OUT |= MOTOR_A_PIN;
P1OUT &= ~MOTOR_B_PIN;
}
else if (motorSpeed < 0)
{
P1OUT |= MOTOR_B_PIN;
P1OUT &= ~MOTOR_A_PIN;
}
else
{
P1OUT &= ~(MOTOR_A_PIN | MOTOR_B_PIN);
}
}
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // 停用看门狗定时器
// 初始化
initPWM();
initEncoder();
initMotor();
initPID();
__enable_interrupt(); // 允许中断
unsigned int timer = 0; // 计时器变量,单位为毫秒
while (1)
{
// 主循环中可以添加其他的控制逻辑
if (timer < 2000) // 前5秒
{
// 示例:将电机速度设置为目标速度
setMotorSpeed(TARGET_SPEED);
}
else if (timer < 2000) // 后5秒
{
// 示例:将电机速度设置为不同的目标速度
setMotorSpeed(-TARGET_SPEED);
}
else
{
// 其他时间段的逻辑
}
// 示例:读取编码器计数值
int currentCount = encoderCount;
// 示例:使用PID控制器计算控制量
error = TARGET_SPEED - currentCount;
integral += error;
derivative = error - previousError;
double controlOutput = Kp * error + Ki * integral + Kd * derivative;
// 示例:根据控制量调整电机速度
setMotorSpeed((int)controlOutput);
previousError = error;
// 示例:延时一段时间
__delay_cycles(1000); // 延时1ms
timer += 1; // 增加计时器
}
return 0;
}
#pragma vector=PORT1_VECTOR
__interrupt void encoderInterrupt(void)
{
if (P1IFG & ENCODER_A_PIN)
{
// 处理编码器A相中断事件
if (P1IN & ENCODER_B_PIN)
{
encoderCount++;
}
else
{
encoderCount--;
}
P1IFG &= ~ENCODER_A_PIN;
}
if (P1IFG & ENCODER_B_PIN)
{
// 处理编码器B相中断事件
if (P1IN & ENCODER_A_PIN)
{
encoderCount--;
}
else
{
encoderCount++;
}
P1IFG &= ~ENCODER_B_PIN;
}
}