| 
 | 
楼主
 
查看: 9942回复: 1
发表于 2020-10-27 20:25:13
  只看该作者
 
 
 
 
摘要 
本系统由主控核心模块,角度信息采集模块,电机驱动控制模块,虚线轨道循迹模 
块等组成。系统采用采用 MSP432 单片机作为小车的检测和控制核心;采用红外传感器获 
取轨道信息,来对小车的方向和速度进行控制。使用角度传感器,把信号反馈到的送单 
片机,使单片机按照预定的工作模式控制小车在坡度不同的情况下按不同的速度行驶; 
通过 L293D 驱动芯片以及 PWM 控制电机,实现直线行驶和转弯。此外,对整个软件进行 
设计和程序的编制以及程序的调试,并最终完成软件和硬件的融合,实现小车的预期功 
能。 
关键词:MSP432 虚线循迹 四轮电动小车 角度传感器 
目录 
一、方案论证 ........................................................................................................................................................................... 1 
1.1 角度信息采集模块的选择 .................................................................................................................................. 1 
1.2 电动机驱动控制模块的选择 .............................................................................................................................. 1 
1.3 虚线轨道循迹模块选择 ....................................................................................................................................... 2 
1.4 总控制系统模块选择 ........................................................................................................................................... 2 
二、理论分析与计算 ............................................................................................................................................................. 2 
2.1 小车速度与方向调节 ........................................................................................................................................... 2 
2.2 红外传感器检测黑白虚线标记线 .................................................................................................................... 2 
三、电路与程序设计 ............................................................................................................................................................. 3 
3.1 系统电路设计 ......................................................................................................................................................... 3 
3.1.1 MSP432P401R SimpleLink™ 微控制器 ............................................................................................ 3 
3.1.2 电机驱动电路 ........................................................................................................................................... 4 
3.1.3 红外循迹电路 ........................................................................................................................................... 4 
3.1.4 电源稳压电路 ........................................................................................................................................... 4 
3.1.5 蜂鸣器电路 ................................................................................................................................................ 5 
3.2 系统程序设计 ......................................................................................................................................................... 5 
3.2.1 程序功能描述 .......................................................................................................................................... 5 
3.2.2 程序设计思路 .......................................................................................................................................... 5 
四、测试方案与测试结果.................................................................................................................................................... 6 
4.1 测试方案................................................................................................................................................................... 6 
4.2 测试结果及分析 ..................................................................................................................................................... 6 
五、总结 .................................................................................................................................................................................... 6 
六、参考文献 ........................................................................................................................................................................... 7 
附录 1:电路原理图 .............................................................................................................................................................. 8 
附录 2:源程序 ....................................................................................................................................................................... 9 
1 
坡道行驶电动小车( C 题) 
【本科组】 
一、方案论证 
本系统主要由角度信息采集模块,电机驱动控制模块,虚线轨道循迹模块和总控制 
系统模块组成,下面分别论证这几个模块的选择。 
1 1.1 角度 信息采集模块 的选择 
方案一:采用电阻器加上 AD 转换器组合成角度传感器,电阻加上一个电压值,滑动 
端可产生电压,旋转电阻器的轴可改变滑动端的电压,通过 AD 转换器将电压信号输入单 
片机即可得到旋转的角度。但是使用 AD 转换器会使用过多的单片机资源,而且电阻器有 
较大的阻尼,如果加上重物太重会影响小车的爬坡能力。 
方案二:采用 MPU6050 角度传感器,MPU6050 由四部分组成:加速度计、陀螺仪、 
DMP、温度传感器(检测温度,通过算法优化来减少温漂)。JY60 和 MPU6050 为从属关系。 
六轴模块 JY60 自带稳压电路,包含陀螺仪加速度计 MPU6050 和 STM8 单片机,STM8 通过 
IIC 读取 MPU6050 中 DMP 的测量数据然后通过串口输出,免去了用户自己去开发 
MPU6050 复杂的 IIC 协议;同时保留了 MPU6050 的 IIC 接口,以满足用户访问底层测 
量数据(加速度、角速度)的需求。 
综合以上两种方案,采用方案二。 
2 1.2 电动机驱动 控制 模块的选择 
方案一:采用继电器对电动机的开或关进行控制,通过开关的切换对小车的速度进 
行调整,这个方案的优点是电路简单,将电机驱动不分隔离了,缺点是继电器响应时间 
慢,机械机构易损坏,寿命短、可靠性不高。 
方案二:采用 DA 转换器,可以输出精确的电压值,经过运算放大器可以将电压放大 
一定倍数,再用运算放大器组成射极跟踪器输出电压,然后驱动电机运转,不过运放驱 
动能力有限。 
方案三:采用但林顿管组成的 H 型 PWM 电路。用单片机控制达林顿管使之工作在占 
空比可调的开关状态,精确调整电动机转速。这种电路由于工作在管子的饱和截止模式, 
效率非常的高,H 桥保证了可以简单的实现转速和方向的控制,电子开关的速度 
很快,稳定性很强,是一种广泛采用的 PWM 调速技术。 
方案 四:采用集成电路 L293D,L293D 是 SGS 公司的产品,内部包含 4 通道逻辑驱动 
电路。可以方便的驱动两个直流电机,或一个两相步进电机。L293D 芯片可以驱动两个二 
相电机,输出电压最高可达 50V,可以直接通过电源来调节输出电压;可以直接用单片机的 
IO 口提供信号;而且电路简单,使用比较方便。 
2 
综合以上四种方案,采用方案四。 
3 1.3 虚线轨道 循 迹模块选择 
方案一:采用灰度传感器检测黑白虚线标记线。灰度传感器是模拟传感器,利用光 
敏电阻对不同颜色的检测面对光的反射程序不同,其阻值变化在的原理进行颜色深浅检 
测。但是外界光线的强弱对其影响非常大,会直接影响到检测效果,在对具体项目检测 
时注意包装传感器,避免外界光的干扰。检测面的材质不同也会引起其返回值的差异。 
方案 二 :采用红外传感器检测黑白虚线标记线。红外传感器巡线的基本原理是利用 
物体的反射性质,当红外线发射到黑线上时会被黑线吸收掉,发射到其他的颜色的材料 
上会有反射到红外的接受管上。并且它结构简明,实现方便,成本低廉,反应灵敏,便 
于近距离路面情况的检测,抗干扰能力强,不会因为周围环境的差别而产生不同的结果。 
综合以上两种方案,采用方案二。 
1.4 4 总控制系统 模块选择 
根据本次赛题要求以及小车控制需求,控制系统芯片选用 MSP432P401R 芯片来接收 
采集的信号以及发出指令。 
二、理论分析与计算 
1 2.1 小车速度与方向调节 
通过 PWM 调节输出电压可以控制左右直流减速电机的转动速度,就可以实现小车的 
速度调节以及方向控制。使两个电机转速一致,可以实现小车直线行走。调节左右轮的 
转动速度,可以实现小车的方向调节。为了使小车行驶姿态流畅,令两个轮子一直保持 
同向转动,抛弃内侧轮子反向转动实现转弯的方法。若想要小车向右侧行驶,则左轮 PWM 
使输出电压占空比大于右轮,即左轮转速较高,实现右转。左转同理。 
2 2.2 红外传感器检测黑白虚线标记线 
红外传感器在小车行驶过程中不断地向地面发射红外光,当红外光遇到白色纸质地 
板时发生漫反射,反射光被装在小车上的接收管接收;如果遇到黑线则红外光被吸收, 
小车上的接收管接收不到红外光。单片机就是否收到反射回来的红外光为依据来确定黑 
线的位置和小车的行走路线。由于路线指示为 1cm×1cm 黑白间隔的纸条,调节传感器位 
置使两路传感器分别在标记线两侧,当小车偏移标记线时,传感器检测到标记线边界, 
将信号传回单片机,继而由单片机向 L293D 驱动芯片发出信号,通过 PWM 控制小车的左 
右电机来调整小车行驶方向,实现循迹前进。因为题目为虚线循迹,所以还增加了一个 
四路循迹来辅助小车。 
3 
三、电路与程序设计 
1 3.1 系统电路设计 
系统采用 MSP432 作为小车的检测和控制核心,通过红外传感器获取轨道信息,来对 
小车的方向进行控制,L293D 驱动芯片控制电机,实现指定距离直线行驶和指定角转弯, 
通过角度传感器控制小车在坡度不同的情况下按不同的速度行驶。停车时,蜂鸣器发出 
声音信号。通过两节电池进行供电,由转接板进行电压处理,通过转接板连接到 msp432 
的 J6 模块,进行供电。连线系统原理图如图 3.1. 
图 3.1 系统原理图 
3.1.1 MSP432P401R SimpleLink™ 微控制器 
SimpleLink MSP‑EXP432P401R LaunchPad 开发套件是一款简单易用的评估模块,适 
用于 MSP432P401R 微控制器。它包含在 MSP432 低功耗高性能 ARM 32 位 Cortex-M4F 微 
控制器 (MCU) 上进行开发所需的全部资源,其中包括用于编程、调试和能量测量的板载 
调试探针。MSP432P401R 器件可支持低功耗应用提升 CPU 速度、存储器、模拟和 32 位性 
能。MSP432P401R 是 MSP432 系列器件中首款具有 ARM Cortex-M4F 内核的低功耗高性能产 
品。利用 40 引脚插座和多种 BoosterPack™插接模块,可以实现无线连接、图形显示、环 
境感测等多项技术,这为快速进行原型设计提供了便利。 
角度信息采集模块 
MSP432P401R 
电源 
红外循迹电路 
电机驱动电路 
蜂鸣器 
4 
图 3.1.1MSP-EXP432P401R 概览 
3.12 .2 电机驱动电路 
系统使用 L293D 芯片驱动电机。L293D 芯片是利用 TTL 电平进行控制,对电机的操作 
方便,MSP432 通过 PWM 调制 I/O 口输出占空比来改变 L293D 芯片控制端的输入电平,即 
可对电机进行正反转操作,来驱动电机转动方向,在单片机中编程改变输出方波的占空 
比就可以改变加到电机上的平均电压,从而可以改变电机的转速。既方便了 MSP432 核心 
芯片的控制,又满足直流减速电机的需求。左右两轮两个电机转速的配合就可以实现小 
车的前进、转弯等功能。驱动电路见附录。 
L293D 芯片为单块集成电路,高电压,高电流,四通道驱动,设计用来接收 DTL 或 
TTL 逻辑电平,驱动感性负载(如继电器,直流或步进马达)。它可以直接对电机进行控 
制,无需隔离电路。调试时依照下表,用程序输入对应码值,即可实现对应的动作。 
表 1 输入电压与行驶状态 
小车行驶状态 INPUT1(与 INPUT2)输入电压 INPUT3(与 INPUT4)输入电压 
直行 左右相等且不为零 左右相等且不为零 
左转 左小 右大 
右转 左大 右小 
停止 电压为零 电压为零 
3.1. .3 3 红外循迹 电 路 
红外传感器巡线的基本原理是利用物体的反射性质,我们本次竞赛是巡黑白虚线行 
驶,采用的是二路+二路红外传感器分别连接在 MSP432 板上,两路巡线传感器分布虚线 
两边,两个二路并列。对于其中一个模块,当黑线段在中间,小车会直行,当任意一个 
检测到黑线,则小车会自动纠正。本次使用的红外循迹模块通过输出 0 和 1 来分别两种 
地面。只需要接上 VCC,GND 电源,将模块输出接到 ms432 的 I/O 口,I/O 口设置为 in 
模式,读取数据。另外一个模块使用 L0 循迹,若检测为黑则执行右拐程序。循迹电路见 
附录。 
3.1. .4 4 电 源稳压 电路 
本系统采用 2 节 14500 锂电池为小车供电,电压达到 7.4V,通过稳压芯片 7805,稳 
定输出电压给单片机、电机和其他芯片供电,确保电路稳定工作。三端 IC 是指这种稳压 
用的集成电路,只有三条引脚输出,分别是输入端、接地端和输出端。7805 三端稳压 IC 
内部电路具有过压保护、过流保护、过热保护功能,这使它的性能很稳定。电路图见附 
录。 
5 
3.1. .5 5 蜂鸣器 电路 
为了实现停车的同时发出声音提示,小车系统还另外装载了有源蜂鸣器,由 P5.6 直 
接控制,电路连接简单,结构不再赘述。电路图见附录。 
3.2 2 系统程序设计 
3.2.1 1 程序功能描述 
首先打开小车电源开关,将小车放入赛道,小车自动循迹前进,到终点标记线时, 
蜂鸣器响并停车。调整赛道角度,小车均以匀速完成上述操作。程序流程图如图 3.5. 
图 3.5 程序流程图 
3.2. .2 2 程序设计思路 
先设计出每种功能中相同的程序部分方便在各个步骤中调用,再设计出各个步骤中 
特有的部分加上之前的公共部分进而完成整个步骤。使用函数库简化程序编写方式。循 
迹判断模块使用 switch 和 case 语句相结合,不同的返回值选择小幅度右拐,大幅度右 
拐,前进,后退函数。蜂鸣器为有源,只需要使用 I/O 口输出高电平即可发声。因为不 
同坡度所需要速度不同,通过按键来改变电机 PWM 占空比,坡度陡时,使速度较小。 
6 
四、测试方案与测试结果 
1 4.1 测试方案 
测试仪器:带一米长黑白间隔纸条标记线的木板(纸条按要求粘贴),秒表,量角 
器,测试环境室内。测试方法:根据木板按照不同倾角摆放,分别记录小车行驶时间 
及行驶状况,根据实际情况分析小车与要求的误差,进行改进提高。测试内容:1)坡 
度角 θ =0°,电动小车沿标记线自动骑线行驶,在停车点停车;停车时蜂鸣器发声。2) 
坡度角 θ =10°,电动小车沿标记线自动骑线匀速行驶,时间控制在 15 秒。在停车点停 
车。3)坡度角 θ =20°,电动小车沿标记线自动骑线匀速行驶,时间控制为 15 秒。在停 
车点停车。4)继续升高赛道坡度角,直到小车不能匀速爬坡及匀速行驶完标记线长度, 
记录此时坡角。5)所有测试中,小车行走稳定,行驶过程中不碾压、脱离标记线,时间 
误差较小。 
2 4.2 测试结果及分析 
在实测过程中,小车能够完成 3 个主要的测试内容,从测试数据可以直观的看到小 
车所能达到的极限坡角为 37°。从几次重复测试的结果可以看出,每次小车循迹行驶时 
都很顺利,说明系统每次行驶及爬坡时没有太大的偏移量,稳定性良好。小车爬坡时与 
转弯后直行时速度相同,这是本次题目的主要考察点。 
从这次测试可以看出,小车已经具备了稳定性,系统程序合格,但从总的表现来看, 
还可以继续改进,争取在 20s 的时间内爬上角度更大的坡。 
五、总结 
本队设计的智能小车的控制机制是:以 MSP432 单片机为控制核心的智能自动循迹行 
驶小车。采用红外探测法实现信号检测,通过红外发射管和接受管来感知给定轨迹,将感 
知的信号返回给单片机,然后单片机对不同信号进行区分,结合软件编程控制小车前进、 
转向,从而实现循迹功能。 
进行电赛设计的过程中,在动手操作的同时也学到了单片机以及相关软件的知识。 
也由于自身理论知识的欠缺和动手能力的不佳在工作中频频受阻,走了好多弯路,虽然 
在制作过程中不可避免地遇到很多问题,但是最后还是在老师以及同学的帮助下圆满解 
决了这些问题,小车最终可以较好地完成基本部分任务。通过这次电赛,队伍成员了解 
并掌握了传感器的基本理论知识,更深入的掌握单片机的开发应用和编程控制。 
7 
六、参考文献 
[1]罗钧,李华,付丽,侍宝玉.基于 MSP432 的多传感器数据采集与动态显示实验设计[J]. 
实验技术与管理,2018,35(10):32-36+44. 
[2]李宏伟.基于 MSP432 的高精度质检秤设计[J].通信电源技术,2020,37(01):109-111. 
[3].德州仪器推出 32 位 MSP432(TM)微控制器[J].电脑与电信,2015(03):9-10. 
[4]陈鸿茂.常用电子元器件简要手册[M].中国矿业大学出版社,2010. 
[6]付杨.电路与电子技术试验教程[M].机械工业出版社,2009. 
[7]胡宴如.模拟电子技术[M].北京高等教育出版社,2008. 
[8]路而红.虚拟电子电子实验室——ElectronicsWorkbench[M]. 北京人民邮电出版 
社,2008. 
8 
附录 1:电路原理图 
9 
电机驱动电路 电源稳压电路 
循迹模块电路 蜂鸣器电路 
附录 2:源程序 
#include "stdint.h" 
#include "msp.h" 
#include "Reflectance.h" 
#include "Clock.h" 
#include "TExaS.h" 
#include "Motor.h" 
#include "xunji.h" 
#include "UART0.h" 
#include <stdio.h> 
#include "CortexM.h" 
uint8_t Data; // QTR-8RC 
int main(void){ 
Clock_Init48MHz(); 
Reflectance_Init(); 
Motor_Init(); 
10 
UART0_Initprintf(); 
Data = 0x00; 
int L = 2500,R = 2500;//L 表示左轮的占空比;R 表示右轮的占空比;取值范围:0~15000 
while(Data != 0x0c) 
{ 
Data = Reflectance_Read(500); 
Port1_Output(Data>>5); 
xunji(Data,L,R); 
} 
while(1) 
{ 
Motor_Stop(); 
} 
} 
///////////////////////////////////////////////////////////////////////////////////////////////// 
///////////////////////xunji.c 
///////////////////////////////////////////////////////////////////////////////////////////////// 
#include "stdint.h" 
#include "Clock.h" 
#include "msp.h" 
#include "xunji.h" 
#include "Motor.h" 
#include <stdio.h> 
#include <string.h> 
#include "Reflectance.h" 
void xunji(uint8_t data,int L,int R) 
{ 
switch(data){ 
case 0x00:// 0000_0000 
otor_Forward(L,R); 
break; 
case 0x0c: //0000_1100 
Motor_Stop(); 
P5->SEL0 = 0x00; 
P5->SEL1 = 0x00;//configure P5.O-P5.1 as GPIO 
P5->DIR = 0x40;//make P5.6 out 
P5->OUT = 0x40;//out 0100 0000 
Clock_Delay1ms(500); 
11 
P5->OUT = 0x00;//out 0100 0000*/ 
break; 
case 0x2c: //0010_1100 
Motor_Stop(); 
P5->SEL0 = 0x00; 
P5->SEL1 = 0x00;//configure P5.O-P5.1 as GPIO 
P5->DIR = 0x40;//make P5.6 out 
P5->OUT = 0x40;//out 0100 0000 
Clock_Delay1ms(500); 
P5->OUT = 0x00;//out 0100 0000*/ 
break; 
case 0x08: //0000_1000 
Motor_Left(L-1200,R+1250); 
break; 
case 0x04: //0000_0100 
Motor_Right(L+2000,R-1250); 
Clock_Delay1ms(60); 
break; 
case 0x20: //0010_0000 
Motor_Right(L+2000,R-1250); 
Clock_Delay1ms(60); 
break; 
case 0x24: //0010_0100 
Motor_Right(L+2000,R-1250); 
Clock_Delay1ms(60); 
break; 
default: 
break; 
} 
} 
///////////////////////////////////////////////////////////////////////////////////////////////// 
/////////////////////// Reflectance.c 
///////////////////////////////////////////////////////////////////////////////////////////////// 
#include "stdint.h" 
#include "msp432.h" 
#include "Clock.h" 
#include "Reflectance.h" 
void Port1_Output(uint8_t data){ // write all of P1.0 outputs 
P1->OUT = (P1->OUT&0xFE)|data; //1111 1110 
} 
void Reflectance_Init(void){ 
12 
P3->SEL0 &= ~0x2c;//1101_0011 ~0010 1100 
P3->SEL1 &= ~0x2c;// 
P3->DIR &= ~0x2C; // P3.3-3.2 input &0010_0011 
P1->SEL0 &= ~0x01; 
P1->SEL1 &= ~0x01; // 1) configure P1.0 as GPIO 1111 1110 
P1->DIR |= 0x01; // 2) make P1.0 out 0000 0001 
} 
// ------------Reflectance_Read------------ 
uint8_t Reflectance_Read(uint32_t time){ 
uint8_t result; 
P3->DIR |= 0xd3; // P3.7-3.6 3.4 3.1-3.0 output=0 1101 0011 
P3->OUT &= 0x2C; // Set P3.7-3.6 3.4 3.1-3.0 low 0010 1100 
Clock_Delay1us(10); 
P3->DIR &= ~0x2C; // P3.2-3.3 input=1 0010 1100 
P3->REN &= ~0xFF; 
Clock_Delay1us(time); 
result = P3->IN; 
return result; 
} 
// ------------Reflectance_Center------------ 
uint8_t Reflectance_Center(uint32_t time){ 
int32_t position=0; 
position = Reflectance_Position(Reflectance_Read(8000)); 
if(position>332 || position<-332) return 0; // off road 
else if(position<0) return 1; // off to right 
else if(position>0) return 2; // off to left 
else return 3; //on road 
} 
int32_t Reflectance_Position(uint8_t data){ 
uint8_t i; 
int32_t position=0, sum_b=0, sum_bw=0; 
const int32_t w[8] = {332,237,142,47,-47,-142,-237,-332}; 
int8_t b[8] = {0,0,0,0,0,0,0,0}; 
int32_t bw[8] = {0,0,0,0,0,0,0,0}; 
if(!data) return 666; 
else{ 
for(i=0;i<8;i++){ 
13 
b[i] = (data>>i)&0x01; 
sum_b += b[i]; 
bw[i] = w[i]*b[i]; 
sum_bw += bw[i]; 
} 
position = sum_bw/sum_b; 
return position; 
} 
} 
// ------------Reflectance_Start------------ 
void Reflectance_Start(void){ 
P3->DIR |= 0x0C; // P3.2-3.3 output 
P3->OUT |= 0x0C; // Set P3.2-3.3 high 
Clock_Delay1us(10); 
P3->DIR &= ~0x0C; // P3.2-3.3 input 
} 
// ------------Reflectance_End------------ 
uint8_t Reflectance_End(void){ 
// write this as part of Lab 10 
uint8_t result; 
result = P3->IN; 
return result; 
} 
///////////////////////////////////////////////////////////////////////////////////////////////// 
/////////////////////// PWM.c 
///////////////////////////////////////////////////////////////////////////////////////////////// 
#include "msp.h" 
//***************************PWM_Init1******************************* 
void PWM_Init1(uin**_t period, uin**_t duty){ 
if(duty >= period) return; // bad input 
P2->DIR |= 0x10; // P2.4 output 
P2->SEL0 |= 0x10; // P2.4 Timer0A functions 
P2->SEL1 &= ~0x10; // P2.4 Timer0A functions 
TIMER_A0->CCTL[0] = 0x0080; // CCI0 toggle 
TIMER_A0->CCR[0] = period; // Period is 2*period*8*83.33ns is 1.333*period 
TIMER_A0->EX0 = 0x0000; // divide by 1 
TIMER_A0->CCTL[1] = 0x0040; // CCR1 toggle/reset 
TIMER_A0->CCR[1] = duty; // CCR1 duty cycle is duty1/period 
TIMER_A0->CTL = 0x0230; // SMCLK=12MHz, divide by 1, up-down mode 
} 
//***************************PWM_Init12******************************* 
14 
void PWM_Init12(uin**_t period, uin**_t duty1, uin**_t duty2){ 
if(duty1 >= period) return; // bad input 
if(duty2 >= period) return; // bad input 
P2->DIR |= 0x30; // P2.4, P2.5 output 
P2->SEL0 |= 0x30; // P2.4, P2.5 Timer0A functions 
P2->SEL1 &= ~0x30; // P2.4, P2.5 Timer0A functions 
TIMER_A0->CCTL[0] = 0x0080; // CCI0 toggle 
TIMER_A0->CCR[0] = period; // Period is 2*period*8*83.33ns is 1.333*period 
TIMER_A0->EX0 = 0x0000; // divide by 1 
TIMER_A0->CCTL[1] = 0x0040; // CCR1 toggle/reset 
TIMER_A0->CCR[1] = duty1; // CCR1 duty cycle is duty1/period 
TIMER_A0->CCTL[2] = 0x0040; // CCR2 toggle/reset 
TIMER_A0->CCR[2] = duty2; // CCR2 duty cycle is duty2/period 
TIMER_A0->CTL = 0x02F0; // SMCLK=12MHz, divide by 8, up-down mode 
} 
//***************************PWM_Duty1******************************* 
void PWM_Duty1(uin**_t duty1){ 
if(duty1 >= TIMER_A0->CCR[0]) return; // bad input 
TIMER_A0->CCR[1] = duty1; // CCR1 duty cycle is duty1/period 
} 
//***************************PWM_Duty2******************************* 
void PWM_Duty2(uin**_t duty2){ 
if(duty2 >= TIMER_A0->CCR[0]) return; // bad input 
TIMER_A0->CCR[2] = duty2; // CCR2 duty cycle is duty2/period 
} 
//***************************PWM_Init34******************************* 
void PWM_Init34(uin**_t period, uin**_t duty3, uin**_t duty4){ 
if(duty3 >= period) return; // bad input 
if(duty4 >= period) return; // bad input 
P2->DIR |= 0xC0; // P2.6, P2.7 output 
P2->SEL0 |= 0xC0; // P2.6, P2.7 Timer0A functions 
P2->SEL1 &= ~0xC0; // P2.6, P2.7 Timer0A functions 
TIMER_A0->CCTL[0] = 0x0080; // CCI0 toggle 
TIMER_A0->CCR[0] = period; // Period is 2*period*8*83.33ns is 1.333*period 
TIMER_A0->EX0 = 0x0000; // divide by 1 
TIMER_A0->CCTL[3] = 0x0040; // CCR3 toggle/reset 
TIMER_A0->CCR[3] = duty3; // CCR3 duty cycle is duty3/period 
TIMER_A0->CCTL[4] = 0x0040; // CCR4 toggle/reset 
TIMER_A0->CCR[4] = duty4; // CCR4 duty cycle is duty4/period 
TIMER_A0->CTL = 0x02F0; // SMCLK=12MHz, divide by 8, up-down mode 
} 
15 
//***************************PWM_Duty3******************************* 
void PWM_Duty3(uin**_t duty3){ 
if(duty3 >= TIMER_A0->CCR[0]) return; // bad input 
TIMER_A0->CCR[3] = duty3; // CCR1 duty cycle is duty1/period 
} 
//***************************PWM_Duty4******************************* 
void PWM_Duty4(uin**_t duty4){ 
if(duty4 >= TIMER_A0->CCR[0]) return; // bad input 
TIMER_A0->CCR[4] = duty4; // CCR1 duty cycle is duty1/period 
} 
///////////////////////////////////////////////////////////////////////////////////////////////// 
/////////////////////// Motor.c 
///////////////////////////////////////////////////////////////////////////////////////////////// 
#include "stdint.h" 
#include "msp.h" 
#include "CortexM.h" 
#include "PWM.h" 
void Motor_Init(void){ 
P1->SEL0 &= ~0xC0; 
P1->SEL1 &= ~0xC0; // configure as GPIO 
P1->DIR |= 0xC0; // make P1.6 & P1.7 out 
P1->OUT &= ~0xC0; 
P3->SEL0 &= ~0xC0; 
P3->SEL1 &= ~0xC0; // configure as GPIO 
P3->DIR |= 0xC0; // make P3.6 & P3.7 out 
P3->OUT &= ~0xC0; // low current sleep mode 
} 
// ------------Motor_Stop------------ 
void Motor_Stop(void){ 
P1->OUT = 0x00; // set direction of motors 
P2->OUT = 0x00; 
PWM_Init34(15000, 0, 0); 
//P3->OUT |= 0xC0; // activate motors 
//P1->OUT &= ~0xC0; 
//P2->OUT &= ~0xC0; // off 
//P3->OUT &= ~0xC0; // low current sleep mode 
} 
16 
// ------------Motor_Forward------------ 
void Motor_Forward(uin**_t leftDuty, uin**_t rightDuty){ 
P1->OUT &= ~0xC0; // set direction of motors 
PWM_Init34(15000, rightDuty, leftDuty); 
} 
// ------------Motor_Right------------ 
void Motor_Right(uin**_t leftDuty, uin**_t rightDuty){ 
P1->OUT &= ~0x80; // left wheel forward 01111 1111 
P1->OUT &= ~0x40; // right wheel forward 1011 1111 
PWM_Init34(15000, rightDuty, leftDuty); 
} 
// ------------Motor_Left------------ 
void Motor_Left(uin**_t leftDuty, uin**_t rightDuty){ 
P1->OUT &= ~0x40; // right wheel forward 0010 0000 
P1->OUT |= 0x80; // left wheel backward 
PWM_Init34(15000, rightDuty, leftDuty); 
} 
// ------------Motor_Backward------------ 
void Motor_Backward(uin**_t leftDuty, uin**_t rightDuty){ 
P1->OUT |= 0xC0; // set direction of motors 
PWM_Init34(15000, rightDuty, leftDuty); 
P3->OUT |= 0xC0; // activate motors 
} 
///////////////////////////////////////////////////////////////////////////////////////////////// 
/////////////////////// Clock.c 
///////////////////////////////////////////////////////////////////////////////////////////////// 
#include <stdint.h> 
#include "msp.h" 
uint32_t ClockFrequency = 3000000; // cycles/second 
//static uint32_t SubsystemFrequency = 3000000; // cycles/second 
// ------------Clock_InitFastest------------ 
// Configure the system clock to run at the fastest 
// and most accurate settings. For example, if the 
// LaunchPad has a crystal, it should be used here. 
// Call BSP_Clock_GetFreq() to get the current system 
// clock frequency for the LaunchPad. 
// Input: none 
17 
// Output: none 
uint32_t Prewait = 0; // loops between BSP_Clock_InitFastest() called and PCM 
idle (expect 0) 
uint32_t CPMwait = 0; // loops between Power Active Mode Request and 
Current Power Mode matching requested mode (expect small) 
uint32_t Postwait = 0; // loops between Current Power Mode matching requested 
mode and PCM module idle (expect about 0) 
uint32_t IFlags = 0; // non-zero if transition is invalid 
uint32_t Crystalstable = 0; // loops before the crystal stabilizes (expect small) 
void Clock_Init48MHz(void){ 
// wait for the PCMCTL0 and Clock System to be write-able by waiting for Power Control Manager 
to be idle 
while(PCM->CTL1&0x00000100){ 
// while(PCMCTL1&0x00000100){ 
Prewait = Prewait + 1; 
if(Prewait >= 100000){ 
return; // time out error 
} 
} 
// request power active mode LDO VCORE1 to support the 48 MHz frequency 
PCM->CTL0 = (PCM->CTL0&~0xFFFF000F) | // clear PCMKEY bit field and AMR bit field 
// PCMCTL0 = (PCMCTL0&~0xFFFF000F) | // clear PCMKEY bit field and AMR bit field 
0x695A0000 | // write the proper PCM key to unlock write access 
0x00000001; // request power active mode LDO VCORE1 
// check if the transition is invalid (see Figure 7-3 on p344 of datasheet) 
if(PCM->IFG&0x00000004){ 
IFlags = PCM->IFG; // bit 2 set on active mode transition invalid; bits 1-0 
are for LPM-related errors; bit 6 is for DC-DC-related error 
PCM->CLRIFG = 0x00000004; // clear the transition invalid flag 
// to do: look at CPM bit field in PCMCTL0, figure out what mode you're in, and step through the 
chart to transition to the mode you want 
// or be lazy and do nothing; this should work out of reset at least, but it WILL NOT work if 
Clock_Int32kHz() or Clock_InitLowPower() has been called 
return; 
} 
// wait for the CPM (Current Power Mode) bit field to reflect a change to active mode LDO VCORE1 
while((PCM->CTL0&0x00003F00) != 0x00000100){ 
CPMwait = CPMwait + 1; 
if(CPMwait >= 500000){ 
return; // time out error 
} 
} 
// wait for the PCMCTL0 and Clock System to be write-able by waiting for Power Control Manager 
18 
to be idle 
while(PCM->CTL1&0x00000100){ 
Postwait = Postwait + 1; 
if(Postwait >= 100000){ 
return; // time out error 
} 
} 
// initialize PJ.3 and PJ.2 and make them HFXT (PJ.3 built-in 48 MHz crystal out; PJ.2 built-in 48 MHz 
crystal in) 
PJSEL0 |= 0x0C; 
PJSEL1 &= ~0x0C; // configure built-in 48 MHz crystal for HFXT operation 
// PJDIR |= 0x08; // make PJ.3 HFXTOUT (unnecessary) 
// PJDIR &= ~0x04; // make PJ.2 HFXTIN (unnecessary) 
CS->KEY = 0x695A; // unlock CS module for register access 
CS->CTL2 = (CS->CTL2&~0x00700000) | // clear HFXTFREQ bit field 
0x00600000 | // configure for 48 MHz external crystal 
0x00010000 | // HFXT oscillator drive selection for crystals >4 MHz 
0x01000000; // enable HFXT 
CS->CTL2 &= ~0x02000000; // disable high-frequency crystal bypass 
// wait for the HFXT clock to stabilize 
while(CS->IFG&0x00000002){ 
CS->CLRIFG = 0x00000002; // clear the HFXT oscillator interrupt flag 
Crystalstable = Crystalstable + 1; 
if(Crystalstable > 100000){ 
return; // time out error 
} 
} 
// configure for 2 wait states (minimum for 48 MHz operation) for flash Bank 0 
FLCTL->BANK0_RDCTL = (FLCTL->BANK0_RDCTL&~0x0000F000)|FLCTL_BANK0_RDCTL_WAIT_2; 
// configure for 2 wait states (minimum for 48 MHz operation) for flash Bank 1 
FLCTL->BANK1_RDCTL = (FLCTL->BANK1_RDCTL&~0x0000F000)|FLCTL_BANK1_RDCTL_WAIT_2; 
CS->CTL1 = 0x20000000 | // configure for SMCLK divider /4 
0x00100000 | // configure for HSMCLK divider /2 
0x00000200 | // configure for ACLK sourced from REFOCLK 
0x00000050 | // configure for SMCLK and HSMCLK sourced from 
HFXTCLK 
0x00000005; // configure for MCLK sourced from HFXTCLK 
CS->KEY = 0; // lock CS module from unintended access 
ClockFrequency = 48000000; 
} 
// ------------Clock_GetFreq------------ 
uint32_t Clock_GetFreq(void){ 
19 
return ClockFrequency; 
} 
void delay(unsigned long ulCount){ 
__asm ( "pdloop: subs r0, #1\n" 
" bne pdloop\n"); 
} 
// ------------Clock_Delay1us------------ 
void Clock_Delay1us(uint32_t n){ 
n = (382*n)/100;; // 1 us, tuned at 48 MHz 
while(n){ 
n--; 
} 
} 
// ------------Clock_Delay1ms------------ 
void Clock_Delay1ms(uint32_t n){ 
while(n){ 
delay(ClockFrequency/9162); // 1 msec, tuned at 48 MHz 
n--; 
} 
} 
 |   
 
 
 
 |