4、LCD_Display.c
#include "msp430x42x.h"
/*宏定义,数码管a-g各段对应的比特,更换硬件只用改动以下8行*/
#define d 0x01 // AAAA
#define g 0x02 // F B
#define b 0x04 // F B
#define a 0x08 // GGGG
#define DOTSEG 0x10 // E C
#define e 0x20 // E C
#define f 0x40 // DDDD
#define c 0x80
#define NEGSEG 0x02
/*用宏定义自动生成段码表,很好的写法,值得学习*/
/*更换硬件无需重写段码表*/
const char LCD_Tab[] = {
a + b + c + d + e + f, // Displays "0"
b + c, // Displays "1"
a + b + d + e + g, // Displays "2"
a + b + c + d + g, // Displays "3"
b + c + f + g, // Displays "4"
a + c + d + f +g, // Displays "5"
a + c + d + e + f + g, // Displays "6"
a + b + c, // Displays "7"
a + b + c + d + e + f + g, // Displays "8"
a + b + c + d + f + g, // Displays "9"
a + b + c + e + f + g, // Displays "A"
c + d + e + f + g, // Displays "B"
a + d + e + f, // Displays "C"
b + c + d + e + g, // Displays "D"
a + d + e + f + g, // Displays "E"
a + e + f + g, // Displays "F"
a + c + d + e + f, // Displays "G"
b + c + e + f + g, // Displays "H"
e + f, // Displays "I"
b + c + d + e, // Displays "J"
b + d + e + f + g, // Displays "K"
d + e + f, // Displays "L"
a + c + e + g, // Displays "M"
a + b + c + e + f, // Displays "N"
c + e + g, // Displays "n"
c + d + e + g, // Displays "o"
a + b + c + d + e + f, // Displays "O"
a + b + e + f + g, // Displays "P"
a + b + c + f + g, // Displays "Q"
e + g, // Displays "r"
a + c + d + f +g, // Displays "S"
d + e + f + g, // Displays "t"
a + e + f , // Displays "T"
b + c + d + e + f, // Displays "U"
c + d + e, // Displays "v"
b + d + f + g, // Displays "W"
b + c + d + f + g, // Displays "Y"
a + b + d + e + g, // Displays "Z"
g, // Displays "-"
b, // Displays "'"
0 // Displays " "
};
#undef a
#undef b
#undef c
#undef d
#undef e
#undef f
#undef g
#define AA 10
#define BB AA+1
#define CC BB+1
#define DD CC+1
#define EE DD+1
#define FF EE+1
#define GG FF+1
#define HH GG+1
#define II HH+1
#define JJ II+1
#define KK JJ+1
#define LL KK+1
#define mm LL+1
#define NN mm+1
#define nn NN+1
#define oo nn+1
#define OO oo+1
#define PP OO+1
#define QQ PP+1
#define rr QQ+1
#define SS rr+1
#define tt SS+1
#define TT tt+1
#define UU TT+1
#define VV UU+1
#define WW VV+1
#define YY WW+1
#define ZZ YY+1
#define BR ZZ+1 /* - */
#define DT BR+1 /* ' */
#define SP DT+1 /* 空白 */
/****************************************************************************
* 名 称:LCD_Init()
* 功 能:初始化LCD显示屏。
* 入口参数:无
* 出口参数:无
* 说 明: 在主程序LCD操作之前,需要调用该函数设置LCD参数。
****************************************************************************/
void LCD_Init()
{ char i;
char *pLCD = (char *)&LCDM1; // 取LCDM1寄存器(最低位)的地址
for (i = 0; i < 8; i++) // Clear LCD memory
*pLCD++ = 0; // 清屏
LCDCTL = LCDSG0_1 + LCD4MUX + LCDON; // LCD模式:4mux LCD, segs0-15
BTCTL |= BT_fLCD_DIV128; // 设置 LCD 刷新率
/*刷新率越慢功耗越低,但速度太慢LCD会闪烁*/
}
/****************************************************************************
* 名 称:LCD_DisplayLongDecimal()
* 功 能:在LCD上显示一个带有小数点的长数据。
* 入口参数:Number:显示数值 (-999999~9999999)
DOT :小数点位数(0~3)
* 出口参数:无
* 范 例: LCD_DisplayDecimal( 123456,2); 显示结果: 1234.56 (2位小数)
LCD_DisplayDecimal(-123456,1); 显示结果:-12345.6 (1位小数)
* 说 明: 该函数能够显示满屏7位数字,但执行时间较长,耗电大。
****************************************************************************/
void LCD_DisplayLongDecimal( long int Number, char DOT)
{
char Neg;
char i;unsigned char temp;
char *pLCD = (char *)&LCDM1;
char PolarLocate;
char DispBuff[8];
if(Number<0) {Number=-Number; Neg=1;} //处理负数
else Neg=0;
for(i=0;i<7;i++) //拆分数字
{
DispBuff[i]=Number%10;
Number/=10;
}
for(i=6;i>DOT;i--) //消隐无效"0"
{
if (DispBuff[i]==0) DispBuff[i]=SP;
else break;
}
PolarLocate=i+1; // 负号显示在第一个有效数字左边
if(DOT>3) DOT=255; // 无效的小数点不显示
if(DOT<1) DOT=255; // LCD048段码中只有123位数字有小数点
for(i=0;i<7;i++)
{
temp=LCD_Tab[DispBuff[i]]; //查表
if (DOT==i) temp|=DOTSEG;//显示小数点
if ((PolarLocate==i)&&(Neg)) temp|=NEGSEG;//负号
pLCD[i]=temp; //写入显存
}
}
/****************************************************************************
* 名 称:LCD_DisplayDecimal()
* 功 能:在LCD上显示一个带有小数点的短整型数据。
* 入口参数:Number:显示数值 (-32768~32767)
DOT :小数点位数(0~3)
* 出口参数:无
* 范 例: LCD_DisplayDecimal( 12345,2); 显示结果: 123.45 (2位小数)
LCD_DisplayDecimal(-12345,1); 显示结果:-1234.5 (1位小数)
* 说 明: 该函数显示数值范围小,但执行时间短,耗电小。
****************************************************************************/
void LCD_DisplayDecimal( int Number, char DOT)
{
char Neg;
char i;unsigned char temp;
char *pLCD = (char *)&LCDM1;
char PolarLocate;
char DispBuff[8];
if(Number<0) {Number=-Number; Neg=1;} //处理负数
else Neg=0;
for(i=0;i<7;i++) //拆分数字
{
DispBuff[i]=Number%10;
Number/=10;
}
for(i=6;i>DOT;i--) //消隐无效"0"
{
if (DispBuff[i]==0) DispBuff[i]=SP;
else break;
}
PolarLocate=i+1; // 负号显示在第一个有效数字左边
if(DOT>3) DOT=255; // 无效的小数点不显示
if(DOT<1) DOT=255; // LCD048段码中只有123位数字有小数点
for(i=0;i<7;i++)
{
temp=LCD_Tab[DispBuff[i]]; //查表
if (DOT==i) temp|=DOTSEG;//显示小数点
if ((PolarLocate==i)&&(Neg)) temp|=NEGSEG;//负号
pLCD[i]=temp; //写入显存
}
}
/****************************************************************************
* 名 称:LCD_DisplayLongNumber()
* 功 能:在LCD上显示一个长整数。
* 入口参数:Number:显示数值 (-999999~9999999)
* 出口参数:无
* 范 例: LCD_DisplayNumber( 123456); 显示结果: 123456
LCD_DisplayNumber(-123456); 显示结果:-123456
* 说 明: 该函数能够显示满屏7位数字,但执行时间较长,耗电大。
****************************************************************************/
void LCD_DisplayLongNumber(long int Number)
{
LCD_DisplayLongDecimal(Number,0) ;//整数没有小数点
}
/****************************************************************************
* 名 称:LCD_DisplayNumber()
* 功 能:在LCD上显示一个短整数。
* 入口参数:Number:显示数值 (-32768~32767)
* 出口参数:无
* 范 例: LCD_DisplayNumber( 12345); 显示结果: 12345
LCD_DisplayNumber(-12345); 显示结果:-12345
****************************************************************************/
void LCD_DisplayNumber(int Number)
{
LCD_DisplayDecimal(Number,0) ;//整数没有小数点
}
/****************************************************************************
* 名 称:LCD_DisplayChar()
* 功 能:在LCD上显示一个字符。
* 入口参数:ch :显示内容 可显示字母请参考LCD_Display.h中的宏定义
Location:显示位置 从左至右对应76543210
* 出口参数:无
* 说 明: 调用该函数不影响LCD其他位的显示。但显示数字的函数会覆盖该函数的结
果,因此该函数要在显示数据函数之后调用。
* 范 例: LCD_DisplayChar(AA,4);
LCD_DisplayChar(PP,5);
LCD_DisplayChar(2 ,6); 显示结果: 2PAXXXX
****************************************************************************/
void LCD_DisplayChar(char ch,char Location)
{
char *pLCD = (char *)&LCDM1;
pLCD[Location]=LCD_Tab[ch];
}
/****************************************************************************
* 名 称:LCD_InsertChar()
* 功 能:在LCD最右端插入一个字符。
* 入口参数:ch :插入字符 可显示字母请参考LCD_Display.h中的宏定义
* 出口参数:无
* 说 明: 调用该函数后,LCD所有已显示字符左移一位,新的字符插入在最右端一位。
该函数可以实现滚屏动画效果,或用于在数据后面显示单位。
* 范 例: LCD_DisplayDecimal(1234,1);
LCD_InsertChar(PP);
LCD_InsertChar(FF);显示结果: 123.4PF
****************************************************************************/
void LCD_InsertChar(char ch)
{ char i;
char *pLCD = (char *)&LCDM1;
for(i=6;i>=1;i--) pLCD[i]=pLCD[i-1];
pLCD[0]=LCD_Tab[ch];
}
/****************************************************************************
* 名 称:LCD_ON()
* 功 能:开启LCD显示
* 入口参数:无
* 出口参数:无
* 说 明: 调用该函数将开启LCD显示。开启后LCD仍显示最后一次显示内容
****************************************************************************/
void LCD_ON()
{
LCDCTL |= LCDON;
}
/****************************************************************************
* 名 称:LCD_ON()
* 功 能:关闭LCD显示
* 入口参数:无
* 出口参数:无
* 说 明: 调用该函数将关闭LCD显示,可节省3~5uA电流。该函数不清除显示内容。
****************************************************************************/
void LCD_OFF()
{
LCDCTL &=~ LCDON;
}
/****************************************************************************
* 名 称:LCD_Clear()
* 功 能: 清除LCD显示
* 入口参数:无
* 出口参数:无
* 说 明: 调用该函数将LCD显示清除,但并不关闭LCD模块。
****************************************************************************/
void LCD_Clear()
{ char i;
char *pLCD = (char *)&LCDM1; // 取LCDM1寄存器(最低位)的地址
for (i = 0; i < 8; i++) // Clear LCD memory
{
*pLCD++ = 0; //清屏
}
}
5、Key.c
#include "MSP430x42x.h"
#define KEYBUFF_SIZE 8 /*键盘缓冲区大小,根据程序需要自行调整*/
char KeyBuff[KEYBUFF_SIZE]; //定义键盘缓冲队列数组(FIFO)
char Key_IndexW=0; //键盘缓冲队列写入指针(头指针)
char Key_IndexR=0; //键盘缓冲队列读取指针(尾指针
char Key_Count=0; //键盘缓冲队列内记录的按键次数
char P_KEY1=255; //存放KEY1前一次状态的变量
char N_KEY1=255; //存放KEY1当前状态的变量
char P_KEY2=255; //存放KEY2前一次状态的变量
char N_KEY2=255; //存放KEY2当前状态的变量
char P_KEY3=255; //存放KEY3前一次状态的变量
char N_KEY3=255; //存放KEY3当前状态的变量
#define KEY1_IN (P1IN&BIT5) //KEY1输入IO的定义(P1.5)
#define KEY2_IN (P1IN&BIT6) //KEY2输入IO的定义(P1.6)
#define KEY3_IN (P1IN&BIT7) //KEY3输入IO的定义(P1.7)
#define PUSH_KEY1 0x01
#define PUSH_KEY2 0x02 /*键值宏定义*/
#define PUSH_KEY3 0x04
unsigned char KEY_SR;
#define DISABLE_INT; KEY_SR=__get_SR_register();_DINT();
#define RESTORE_INT; if(KEY_SR & GIE) _EINT();
/****************************************************************************
* 名 称:Key_Init()
* 功 能:初始化键盘所在的IO口
* 入口参数:无
* 出口参数:无
****************************************************************************/
void Key_Init()
{
P1DIR&=~(BIT5+BIT6+BIT7); //P1.5/6/7作为输入
}
/****************************************************************************
* 名 称:Key_InBuff()
* 功 能:将一次键值压入键盘缓冲队列
* 入口参数:Key:被压入缓冲队列的键值
* 出口参数:无
****************************************************************************/
void Key_InBuff(char Key)
{
if(Key_Count>=KEYBUFF_SIZE) return;//若缓冲区已满,放弃本次按键
DISABLE_INT;
Key_Count++; //按键次数计数增加
KeyBuff[Key_IndexW] = Key; //从队列头部追加新的数据
if (++Key_IndexW >= KEYBUFF_SIZE) //循环队列,如果队列头指针越界
{
Key_IndexW = 0; //队列头指针回到数组起始位置
}
RESTORE_INT;
}
/****************************************************************************
* 名 称:Key_GetKey()
* 功 能:从键盘缓冲队列内读取一次键值
* 入口参数:无
* 出口参数:若无按键,返回0,否则返回一次按键键值。
* 说 明: 调用一次该函数,会自动删除缓冲队列里一次按键键值。
****************************************************************************/
char Key_GetKey()
{ char Key;
if(Key_Count==0) return(0); //若无按键,返回0
DISABLE_INT;//队列操作过程中不允许被定时中断执行ScanIO函数,保护全局变量正确
Key_Count--; //按键次数计数减1
Key=KeyBuff[Key_IndexR]; //从缓冲区尾部读取一个按键值
if (++Key_IndexR >= KEYBUFF_SIZE)//循环队列,如果队列尾指针越界
{
Key_IndexR = 0; //队列尾指针回到数组起始位置
}
RESTORE_INT; //恢复中断允许
return(Key);
}
/****************************************************************************
* 名 称:Key_WaitKey()
* 功 能:从键盘缓冲队列内读取一次键值
* 入口参数:无
* 出口参数:若有按键,返回键值,否则等待按键。
* 说 明: 该函数会阻塞CPU继续执行后面的程序,应用时需注意。
****************************************************************************/
char Key_WaitKey()
{ char Key;
while(1)
{
Key=Key_GetKey(); //从键盘缓冲队列读取一次键值
if(Key==0) LPM3; //如果没按键,则停止CPU,等待被唤醒继续读按键
else return(Key); //如果有按键,则返回键值
}
}
/****************************************************************************
* 名 称:Key_ScanIO()
* 功 能:扫描键盘IO口并判断按键事件
* 入口参数:无
* 出口参数:无,键值压入缓冲队列
* 说 明: 该函数需要每隔1/16秒至1/128秒调用一次。最好放在定时中断内执行。
如果中断间隔太长,可能丢键;间隔太短不能消除抖动。
****************************************************************************/
void Key_ScanIO()
{
P_KEY1=N_KEY1; //保存KEY1前一次的状态
N_KEY1=KEY1_IN; //读取KEY1当前的状态
P_KEY2=N_KEY2; //保存KEY2前一次的状态
N_KEY2=KEY2_IN; //读取KEY2当前的状态
P_KEY3=N_KEY3; //保存KEY3前一次的状态
N_KEY3=KEY3_IN; //读取KEY3当前的状态
if((P_KEY1!=0)&&(N_KEY1==0)) Key_InBuff(PUSH_KEY1);
if((P_KEY2!=0)&&(N_KEY2==0)) Key_InBuff(PUSH_KEY2);
if((P_KEY3!=0)&&(N_KEY3==0)) Key_InBuff(PUSH_KEY3);
}
6、jinshu.c
#include "msp430x42x.h"
#include "Uart.h"
#include "LCD_Display.h"
#include "RTC.h"
#define Circle 46
char Jinshu_Shu;//定义检测到金属的片数
unsigned int TA_Overflowcnt;
unsigned long int period;
unsigned int Dis;
unsigned int cnt;
extern char Second;
unsigned int Dis_Shu[4];
void jinshu_Init(void) //金属检测初始化程序
{
Jinshu_Shu=0; //初始化 检测到金属的片数为零
// 初始化 测速 金属检测初始化程序
P1DIR&=~(BIT3+BIT5); //把P1^2,P1.5初始化为输入
P1IES|=BIT3+BIT5; //把其定义为初始化下降沿触发中断
P1IE|=BIT3+BIT5; //p1.3,P1.5中断允许
TACTL=TASSEL_1+MC_2+TAIE+TACLR;
BTCTL=0;
}
#pragma vector =PORT1_VECTOR
__interrupt void PORT1_ISR(void) //p1口中断服务程序
{
unsigned int i;
unsigned int j;
for(i=2000;i>0;i--);//延时进行消除抖动
if (P1IFG & BIT3)
{
//表示小车可能将要进铁片入区域
if((P1IN&BIT3)==0) //表示小车刚进入铁片区域
{ Dis_Shu[Jinshu_Shu]= Dis ;
Jinshu_Shu++; //铁片数目加1
LCD_DisplayChar(Jinshu_Shu,5);
P1IFG=0;
if(Jinshu_Shu==3)
{for(i=0;i<5;i++)
UART0_PutChar(0x02); //停车
}
else
{for(i=0;i<5;i++)
UART0_PutChar(0x01);
}
//LCD_DisplayDecimal(Dis,2);
//可以在这里调用串口通信程序,向MSP149发送信息,打开声光指示程序
}
}
// 与测速有关的部分
_BIC_SR(SCG0);
if((P1IN&BIT5)==BIT5)
{
P1IFG=0;
//return;
}
if (P1IFG & BIT5);
for(j=0;j<2000;j++)
if (P1IFG & BIT5);
{
cnt++;
Dis = cnt * Circle;
//LCD_DisplayDecimal(Dis,1);
}
P1IFG=0;
}
#pragma vector=TIMERA1_VECTOR
__interrupt void TA_ISR(void)
{
switch(TAIV)
{
case 2:break;
case 4:break;
case 10:TA_Overflowcnt++;
break;
}
}
7、UART.c
#include <msp430x14x.h>
#define RXBUF_SIZE 32
#define TXBUF_SIZE 32 //发送FIFO的最大容量
unsigned char RX_BUFF[RXBUF_SIZE];
unsigned int UART_InpLen = 0;
unsigned int RX_IndexR = 0;
unsigned int RX_IndexW = 0;
unsigned char TX_BUFF[TXBUF_SIZE]; //发送FIFO缓冲区数据
unsigned int UART_OutLen=0; //发送FIFO内等待发出的字节数
unsigned int TX_IndexR=0; //发送FIFO的读指针
unsigned int TX_IndexW=0; //发送FIFO的写指针
unsigned char Command[5];
//149串口初始化
UART_Init149()
{
U0CTL |= CHAR; //异步通讯模式,8位数据,无校验,1位停止位
ME1 |= UTXE0 + URXE0; //开启串口0收发模块
U0TCTL |= SSEL0; //选择ACLK作为串口波特率时钟源
U0BR1 = 0; //
U0BR0 = 13; //分频系数整数部分=13
U0MCTL = 0X6B; //分频系数小数部分调制=5/8.(2400bps)
P3SEL |= BIT4 + BIT5;
U0CTL &=~ SWRST; //启动串口
IE1 |= URXIE0;
}
UART_Init425()
{
U0CTL |= CHAR; //异步通讯模式,8位数据,无校验,1位停止位
ME1 |= UTXE0 + URXE0; //开启串口0收发模块
U0TCTL |= SSEL0; //选择ACLK作为串口波特率时钟源
U0BR1 = 0; //
U0BR0 = 13; //分频系数整数部分=13
U0MCTL = 0X6B; //分频系数小数部分调制=5/8.(2400bps)
P2SEL |= BIT4 + BIT5; //
U0CTL &=~ SWRST; //启动串口
IE1 |= URXIE0;
}
/*********************************************************
名称: UART0_GetChar()
功能: 从串口读一个字节数据
入口参数: 数据存放的地址指针
出口参数: 0表示失败,1表示成功
说明: 读取过程不阻塞CPU运行
*********************************************************/
char UART0_GetChar(unsigned char *Chr)
{
if(UART_InpLen == 0) return (0);
_DINT();
UART_InpLen--;
*Chr = RX_BUFF[RX_IndexR];
if (++RX_IndexR >= RXBUF_SIZE)
{ RX_IndexR = 0;
}
_EINT();
return (1);
}
/*********************************************************
名称: UART0_GetCharsInRxBuf()
功能:
入口参数:
出口参数: 待读取的字节数
*********************************************************/
unsigned int UART0_GetCharsInRxBuf()
{
return (UART_InpLen);
}
/*********************************************************
名称: UART0_ClrRxBuf()
功能: 清除接收队列
入口参数:
出口参数:
*********************************************************/
void UART0_ClrRxBuf()
{
_DINT();
UART_InpLen = 0;
RX_IndexR = 0;
RX_IndexW = 0;
_EINT();
}
//串口接收中断
#pragma vector= UART0RX_VECTOR
__interrupt void UART0_RX (void)
{
UART_InpLen ++;
RX_BUFF[RX_IndexW] =U0RXBUF;
if (++RX_IndexW >= RXBUF_SIZE)
{
RX_IndexW = 0;
}
}
/********************************************************************
名称:char UART0_PutChar()
功能:向串口发送一字节
入口参数: Chr,待发字节
出口参数: 返回1成功,0失败
********************************************************************/
char UART0_PutChar(unsigned char Chr)
{
if(UART_OutLen == TXBUF_SIZE)
{
return(0);
}
if(UART_OutLen == 0)
{
IFG1 |= UTXIFG0;
}
_DINT();
UART_OutLen++;
TX_BUFF[TX_IndexW] = Chr;
if (++TX_IndexW >= TXBUF_SIZE)
{
TX_IndexW = 0;
}
IE1 |= UTXIE0;
_EINT();
return (1);
}
//串口发送中断
#pragma vector=UART0TX_VECTOR
__interrupt void UART0_TX (void)
{
if(UART_OutLen>0)
{
UART_OutLen--;
U0TXBUF = TX_BUFF[TX_IndexR];
if(++TX_IndexR >= TXBUF_SIZE)
{
TX_IndexR = 0;
}
}
else IE1 &=~ UTXIE0;
}
|