/***************************************************
最后再附上一个最近做的数控直流电源的源代码,希望大家能一起互相学习:)
***************************************************/
#include <msp430g2452.h>
/********************************************
* TLC5615:
DIN:P1.1 SCLK:P1.2 CS:P1.0
74LS48
A:P1.4 B:P1.5 C:P1.6 D:P1.7
74LS138
A:P2.0 B:P2.1 C:P2.6
按键:
key1:P2.2 key2:P2.3 key3:P2.4 key4:P2.5
*********************************************/
int b[4];
int *pb = &b[0];
int dat = 0;
int time = 0;
int Buff = 0;
//DIN:P1.1 SCLK:P1.2 CS:P1.0
#define DIN_SET BIT1
#define DIN_CLC ~BIT1
#define SCLK_SET BIT2
#define SCLK_CLC ~BIT2
#define CS_SET BIT0
#define CS_CLC ~BIT0
void delay_ms(int tt)
{
for(tt*=500;tt>0;tt--)
{
_nop();
}
}
/*******************************
* 函数名:Clock_Init
* 功能:初始化时钟
* 参数:无
******************************/
void Clock_Init(void)
{
DCOCTL |= CALDCO_1MHZ;
BCSCTL1 |= CALBC1_1MHZ; //初始化DCO时钟频率为 1MHz
}
/*******************************
* 函数名:IO_Init
* 功能:初始化IO口
* 参数:无
******************************/
void IO_Init(void)
{
P1DIR |= 0xFFF7; //P1口所有管脚设为输出模式(除了P1.3,因为P1.3外接了上拉电阻作为S2)
P1OUT &= 0x0000; //复位IO端口
P2SEL &= ~BIT6; //将P2.6设置为通用IO输入
P2DIR |= BIT0 + BIT1 +BIT6; //P2口 0,1,6设为输出模式
P2OUT &= 0x0000; //复位IO端口
P2DIR &= 0x00C3; //P2口2,3,4,5设置为输入模式
P2REN |= BIT2 + BIT3 + BIT4 + BIT5; //设置为上拉输入模式
P2OUT |= BIT2 + BIT3 + BIT4 + BIT5;
}
/*******************************
* 函数名:Key_Scan
* 功能:按键扫描
* 参数:无
* 返回值:z
* z=1:P2.2被按下 “+”
* z=2:P2.3被按下 “-”
* z=3:P2.4被按下 “操作位选择”
* z=4:P2.5被按下 “确认”
******************************/
int Key_Scan(void)
{
int z = 0;
if(!(P2IN&BIT2)) //P2.2被按下
{
delay_ms(5); //延时消抖
if(!(P2IN&BIT2))//确实被按下
{
while(!(P2IN&BIT2)); //松手检测
z = 1;
}
}
if(!(P2IN&BIT3)) //P2.3被按下
{
delay_ms(5); //延时消抖
if(!(P2IN&BIT3))//确实被按下
{
while(!(P2IN&BIT3)); //松手检测
z = 2;
}
}
if(!(P2IN&BIT4)) //P2.4被按下
{
delay_ms(5); //延时消抖
if(!(P2IN&BIT4))//确实被按下
{
while(!(P2IN&BIT4)); //松手检测
z = 3;
}
}
if(!(P2IN&BIT5)) //P2.5被按下
{
delay_ms(5); //延时消抖
if(!(P2IN&BIT5))//确实被按下
{
while(!(P2IN&BIT5)); //松手检测
z = 4;
}
}
return z;
}
/**********************************
* 函数名:Flicker
* 功能:当设置时闪烁选中位
* 参数:*pointer:指向所选中位
* array[]:数据参数
* 返回值:无
**********************************/
//P2.6为C 闪烁控制位
void Flicker(int *pointer,int array[])
{
int i;
int tmp = 0;
for(i = 0;i<4;i++)
{
if(pointer == &array[0]) //第一位闪烁
{
if(tmp == 0)
{
if(time<15)
{
P2OUT |= BIT6;
time++;
}
else
{
if(time<30)
{
P2OUT &= ~BIT6;
time++;
}
else time = 0;
}
}
else
{
P2OUT &= ~BIT6; //若不是闪烁位 则拉低138 C 是数码管段选选通
}
if(tmp%2) //控制段选输出
{
P2OUT |= BIT0; //138 A
}
else
{
P2OUT &= ~BIT0;
}
if(tmp/2)
{
P2OUT |= BIT1; //138 B
}
else
{
P2OUT &= ~BIT1;
}
tmp++;
if(tmp>3)tmp = 0;
}
else if(pointer == &array[1])
{
if(tmp == 1)
{
if(time<15)
{
P2OUT |= BIT6;
time++;
}
else
{
if(time<30)
{
P2OUT &= ~BIT6;
time++;
}
else time = 0;
}
}
else
{
P2OUT &= ~BIT6;
}
if(tmp%2)
{
P2OUT |= BIT0;
}
else
{
P2OUT &= ~BIT0;
}
if(tmp/2)
{
P2OUT |= BIT1;
}
else
{
P2OUT &= ~BIT1;
}
tmp++;
if(tmp>3)tmp = 0;
}
else if(pointer == &array[2])
{
if(tmp == 2)
{
if(time<15)
{
P2OUT |= BIT6;
time++;
}
else
{
if(time<30)
{
P2OUT &= ~BIT6;
time++;
}
else time = 0;
}
}
else
{
P2OUT &= ~BIT6;
}
if(tmp%2)
{
P2OUT |= BIT0;
}
else
{
P2OUT &= ~BIT0;
}
if(tmp/2)
{
P2OUT |= BIT1;
}
else
{
P2OUT &= ~BIT1;
}
tmp++;
if(tmp>3)tmp = 0;
}
else if(pointer == &array[3])
{
if(tmp == 3)
{
if(time<15)
{
P2OUT |= BIT6;
time++;
}
else
{
if(time<30)
{
P2OUT &= ~BIT6;
time++;
}
else time = 0;
}
}
else
{
P2OUT &= ~BIT6;
}
if(tmp%2) //控制数码管段选,闪烁
{
P2OUT |= BIT0;
}
else
{
P2OUT &= ~BIT0;
}
if(tmp/2)
{
P2OUT |= BIT1;
}
else
{
P2OUT &= ~BIT1;
}
tmp++;
if(tmp>3)tmp = 0;
}
if(b[i]&BIT3) //将array[i]转化为二进制输出,经BCD译码,送数码管显示
{
P1OUT |= BIT7;
}
else
{
P1OUT &= ~BIT7;
}
if(b[i]&BIT2)
{
P1OUT |= BIT6;
}
else
{
P1OUT &= ~BIT6;
}
if(b[i]&BIT1)
{
P1OUT |= BIT5;
}
else
{
P1OUT &= ~BIT5;
}
if(b[i]&BIT0)
{
P1OUT |= BIT4;
}
else
{
P1OUT &= ~BIT4;
}
delay_ms(1);
}
}
/**************************************
* 函数名:Set
* 功能:根据按键的值来执行相应的设置
* 参数: keynum:按键的返回值
* 返回值:返回电压值 供DIsp函数显示
***************************************/
int Set(int keynum)
{
b[0] = dat/1000;
b[1] = dat%1000/100;
b[2] = dat%100/10;
b[3] = dat%10;
if(keynum) //有键按下
{
unsigned char flag = 1;
while(flag)
{
switch(keynum)
{
case 1:
{
(*pb)++;
if(*pb>9)*pb = 0;
}break;
case 2:
{
(*pb)--;
if(*pb<0)*pb = 9;
}break;
case 3:
{
pb++;
if(pb>&b[3])pb = &b[0];
}break;
case 4:
{
flag = 0; //若按下确认键 跳出循环
}break;
default:
break;
}
keynum = 0;
keynum = Key_Scan();
Flicker(pb,b);
}
}
dat = b[0]*1000+b[1]*100+b[2]*10+b[3];
}
/****************************************
* 函数名:LED_Disp
* 功能:显示设定输出电压值
* 参数:dat:输入的电压设定参数
* 若 dat = 512;表示设定输出为 5.12V
* 返回值:
* 将设定的温度换算成DA的数据,输入DA
****************************************/
int LED_Disp(int dat)
{
int a[4],tmp = 0;
int i;
a[0] = dat/1000;
a[1] = dat%1000/100;
a[2] = dat%100/10;
a[3] = dat%10;
for(i = 0;i<4;i++)
{
if(tmp%2) //控制数码管段选
{
P2OUT |= BIT0;
}
else
{
P2OUT &= ~BIT0;
}
if(tmp/2)
{
P2OUT |= BIT1;
}
else
{
P2OUT &= ~BIT1;
}
tmp++;
if(tmp>3)tmp = 0;
if(a[i]&BIT3) //将a[i]转化为二进制输出,经BCD译码,送数码管显示
{
P1OUT |= BIT7;
}
else
{
P1OUT &= ~BIT7;
}
if(a[i]&BIT2)
{
P1OUT |= BIT6;
}
else
{
P1OUT &= ~BIT6;
}
if(a[i]&BIT1)
{
P1OUT |= BIT5;
}
else
{
P1OUT &= ~BIT5;
}
if(a[i]&BIT0)
{
P1OUT |= BIT4;
}
else
{
P1OUT &= ~BIT4;
}
delay_ms(2);
}
Buff = (float)dat/1000*1024; //将输入的数字温度值转化为送给DA的数据值
if(Buff > 1023) Buff = 1023;
return Buff;
}
/*******************************
* 函数名:Send_Data
* 功能:写入10位数据
* 参数:dat:10位数据
******************************/
void Send_Data(int dat)
{
int i,tmp = 0x0200;
P1OUT &= CS_CLC; //使能
for(i = 0;i<10;i++)
{
if(dat&tmp)
{
P1OUT |= DIN_SET;
}
else
{
P1OUT &= DIN_CLC;
}
tmp>>=1;
P1OUT |= SCLK_SET; //将数据写入
P1OUT &= SCLK_CLC;
}
P1OUT |= DIN_SET; //写入两个填充位
P1OUT |= SCLK_SET;
P1OUT &= SCLK_CLC;
P1OUT |= DIN_SET;
P1OUT |= SCLK_SET;
P1OUT &= SCLK_CLC;
P1OUT |= CS_SET; //挂起
}
void main(void)
{
int tmp = 0,D = 0;
WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
Clock_Init();
IO_Init();
int i = 0;
P2OUT &= ~BIT6;
for(;;)
{
tmp = Set(Key_Scan());
LED_Disp(tmp);
Send_Data(LED_Disp(tmp));
}
}
|