基于MSP430G2553的模拟风扇控制系统
本次设计是通过CCS和AD15设计的一个模拟风扇控制系统,该系统主要包括独立键盘电路模块、直流稳压电路模
块、程序下载电路模块、数码管显示模块、三极管LED驱动模块、电机驱动电路模块。本次设计方MSP430G2553
为控制核心,合理应用该单片机的资源,以最好的方式实现本设计,并且达到了设计要求中的各项指标。
关键词:MSP430G2553、直流电机、MAX7219驱动、PWM控制
话不多说,直接上代码:
该代码纯属个人编写,仅供参考,小白一个,哈哈哈哈。当然有好多东西没有封装成函数。
下面展示一些 内联代码片
。
// A code block
主函数
// An highlighted block
#include <msp430.h>
#include "stdint.h"
#include "SMG.h"
#include "DS18B20.h"
#include "Inital.h"
#define Point 0x80
const unsigned char tabel[14]={
0x7e, //'0'
0x06, //'1'
0x6d, //'2'
0x79, //'3'
0x33, //'4'
0x5b, //'5'
0x5f, //'6'
0x70, //'7'
0x7f, //'8'
0x7b, //'9'
0x01, //'-'
0x4e, //'C'
0x00 //'不显示'
};
uint8_t time = 0; //时间记录
uint8_t cishu = 0; //50ms*20=1s
uint8_t flag0 = 0; //模式标志位
uint8_t flag1 = 0; //时间标志位
uint8_t flag2 = 0; //判断显示温度标志位
uint8_t model = 0; //模式
uint8_t Model = 0; //模式
uint16_t n=0; //记录当前TACCR2的值
uint8_t Tempreture;
//时间显示
void Display1(void)
{
uint8_t baiwei,shiwei,gewei;
baiwei=time/100;
shiwei=time%100/10;
gewei=time%10;
Write_Max7219(1,tabel[gewei]);
Write_Max7219(2,tabel[shiwei]);
Write_Max7219(3,tabel[baiwei]);
Write_Max7219(4,tabel[0]);
}
//model显示
void Display2(void)
{
Write_Max7219(5,tabel[12]);
Write_Max7219(6,tabel[10]);
Write_Max7219(7,tabel[model]);
Write_Max7219(8,tabel[10]);
}
//温度显示
void Display3(void)
{
uint8_t ge,shi;
shi=Tempreture/10;
ge=Tempreture%10;
Write_Max7219(1,tabel[11]);
Write_Max7219(2,tabel[ge]);
Write_Max7219(3,tabel[shi]);
Write_Max7219(4,tabel[12]);
}
//初始化
void Display_all0(void)
{
Write_Max7219(1,tabel[0]);
Write_Max7219(2,tabel[0]);
Write_Max7219(3,tabel[0]);
Write_Max7219(4,tabel[0]);
Write_Max7219(5,tabel[12]);
Write_Max7219(6,tabel[10]);
Write_Max7219(7,tabel[0]);
Write_Max7219(8,tabel[10]);
}
/*
* main.c
*/
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
InitSystemClock();
InitZHDIO();
InitPWM();
InitTimer0HZD();
Init_Max7219_IO();
Init_Max7219_();
Display_all0();
P1OUT &= ~BIT5;P1OUT &= ~BIT6;P1OUT &= ~BIT7;
/*开启总中断*/
__bis_SR_register(GIE);
while(1)
{
Display1();
Display2();
while(flag2==1)
{
Tempreture = DS18B20_Conert();
Display2();
Display3();
__delay_cycles(2);
}
__delay_cycles(2);
}
}
#pragma vector = PORT1_VECTOR
__interrupt void port1_ISR(void)
{
__delay_cycles(500000); //0.1s消抖
/*P1.1中断,切换模式*/
if(P1IFG&BIT1)
{
P1IFG &= ~BIT1;
switch(flag0)
{
case 0:
if(time!=0)TA1CCR2 = 400; //20%
else TA1CCR2 = 499;
flag0=1;model=1;Model=1;n=400;P1OUT |= BIT5;P1OUT &= ~BIT6;P1OUT &= ~BIT7;
break;
case 1:
if(time!=0)TA1CCR2 = 350; //30%
else TA1CCR2 = 499;
flag0=2;model=2;Model=2;n=350;P1OUT |= BIT6;P1OUT &= ~BIT5;P1OUT &= ~BIT7;
break;
case 2:
if(time!=0)TA1CCR2 = 150; //70%
else TA1CCR2 = 499;
flag0=0;model=3;Model=3;n=150;P1OUT |= BIT7;P1OUT &= ~BIT5;P1OUT &= ~BIT6;
break;
default:
break;
}
Display2();
}
/*P1.2中断,选择时间*/
if(P1IFG&BIT2)
{
TA1CCR2 = n;
P1IFG &= ~BIT2;
TA0CTL &= ~TAIE; /*关闭定时器中断*/
TA0CTL |= TACLR; /*TAR清零,保证重新从0计数*/
switch(flag1)
{
case 0:
time=60;flag1=1;cishu=0; //cishu也清零
break;
case 1:
time=120;flag1=2;cishu=0;
break;
case 2:
time=180;flag1=0;cishu=0;
break;
default:
break;
}
TA0CTL |= TAIE; /*开启定时器中断*/
}
/*P1.3中断,停止*/
if(P1IFG&BIT3)
{
P1IFG &= ~BIT3;
TA1CCR2=499; //PWM停止产生
time=0; //时间归0
flag1=0; //保证从60s开始
P1OUT &= ~BIT5;P1OUT &= ~BIT6;P1OUT &= ~BIT7; //指示灯全部熄灭
}
/*P1.4中断,显示温度*/
if(P1IFG&BIT4)
{
P1IFG &= ~BIT4;
Tempreture = DS18B20_Conert();
if(flag2==1) {flag2=0;model=Model;} //标志位,判断显示温度还是时间
else {flag2=1;model=4;}
}
}
/*定时器中断,倒计时*/
#pragma vector = TIMER0_A1_VECTOR
__interrupt void Timer0ZHD(void)
{
switch(TA0IV) //由于寄存器的共用,需要判断到底是哪个中断被执行
{ //读取了TA0IV后,中断标志位自动清零
case 0x02:
break;
case 0x04:
break;
case 0x0A:
if(cishu==20) //50ms*20=1s
{
cishu=0;
if(time>0)time--;
else
{
time=0;
TA1CCR2=499; //PWM停止产生
}
}
else cishu++;
break;
default:
break;
}
}
头文件:
下面展示一些 内联代码片
。
// A code block
var foo = 'bar';
// An highlighted block
/*
* DS18B20.h
*
* Created on: 2020年12月1日
* Author: duwei
*/
#ifndef DS18B20_H_
#define DS18B20_H_
//P2.4
#define DS18B20_DIR P2DIR
#define DS18B20_OUT P2OUT
#define DS18B20_IN P2IN
#define DS18B20_DQ BIT4
#define DS18B20_H DS18B20_OUT|=DS18B20_DQ //DQ置位
#define DS18B20_L DS18B20_OUT&=~DS18B20_DQ //DQ复位
#define DQ_IN DS18B20_DIR &= ~DS18B20_DQ //设置DQ为输入
#define DQ_OUT DS18B20_DIR |= DS18B20_DQ //设置DQ为输出
#define READ_DQ (DS18B20_IN&DS18B20_DQ) //读DQ电平
#define CPU_F ((double)1000000)
#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))
void DS18B20_init(); //DS18B20初始化
unsigned char DS18B20_Reset(); //DS18B20复位
void DS18B20_WriteData(unsigned char); //写数据到DS18B20
unsigned char DS18B20_ReadData(); //读数据
uint8_t DS18B20_Conert(); //转换温度
#endif /* DS18B20_H_ */
下面展示一些 内联代码片
。
// A code block
var foo = 'bar';
// An highlighted block
#include <msp430.h>
#include "stdint.h"
#include "DS18B20.h"
/**********************************************************
*DS18B20初始化
*函数名称:DS18B20_Init()
*说明:本初始化程序可以不要,因为18B20在出厂时就被配置为12位精度了
**********************************************************/
void DS18B20_Init()
{
DS18B20_Reset();
DS18B20_WriteData(0xCC); // 跳过ROM
DS18B20_WriteData(0x4E); // 写暂存器
DS18B20_WriteData(0x64); // 往暂存器的第三字节中写上限值100℃
DS18B20_WriteData(0x00); // 往暂存器的第四字节中写下限值0℃
DS18B20_WriteData(0x7F); // 将配置寄存器配置为12位精度
DS18B20_Reset();
}
/**********************************************************
*复位DS18B20(通过存在脉冲可以判断DS1820是否损坏)
*函数名称:DS18B20_Reset()
**********************************************************/
unsigned char DS18B20_Reset()
{
unsigned char flag;
DQ_OUT; //DQ为输出
DS18B20_H;
delay_us(8); //延时8微秒
DS18B20_L; //拉低总线
delay_us(500); //延时500微秒,产生复位脉冲,必须大于480微秒
DS18B20_H;
delay_us(80); //15~60us 后接收 60-240us的存在脉冲,必须大于60微秒
DQ_IN;
if(READ_DQ)flag=0; //等待从机 DS18B20 应答(低电平有效)
else flag=1;
DQ_OUT;
delay_us(440);
DS18B20_H;
return(flag);
}
/**********************************************************
*写数据到DS18B20
*函数名称:DS18B20_WriteData()
**********************************************************/
void DS18B20_WriteData(unsigned char wData)
{
unsigned char i;
DQ_OUT; //DQ为输出
for (i=8;i>0;i--)
{
DS18B20_L; //拉低总线,产生写信号
delay_us(15); //延时在15us~30us
if(wData&0x01){DS18B20_H;} //发送1位
else {DS18B20_L;}
delay_us(45); //延时15~60us
DS18B20_H; //释放总线,等待总线恢复
wData>>=1; //准备下一位数据的传送
}
}
/**********************************************************
*从DS18B20中读出数据
*函数名称:DS18B20_ReadData()
**********************************************************/
unsigned char DS18B20_ReadData()
{
unsigned char i,TmepData;
for(i=8;i>0;i--)
{
TmepData>>=1; //数据右移
DQ_OUT; //DQ为输出
DS18B20_L; //拉低总线,产生读信号
delay_us(6);
DS18B20_H; //释放总线,准备读数据
delay_us(4);
DQ_IN; //DQ为输入
if(READ_DQ)
{TmepData|=0x80;}
delay_us(65);
}
return TmepData; //返回读到的数据
}
/**********************************************************
*DS18B20转换温度
*函数名称:DS18B20_Conert()
**********************************************************/
uint8_t DS18B20_Conert(void)
{
unsigned char TempData1,TempData2,wendu;
unsigned int uu;
DS18B20_Reset();
DS18B20_WriteData(0xCC); // 跳过ROM
DS18B20_WriteData(0x44); // 开始转换
delay_us(500); //延时一般在500us不能过小
DS18B20_Reset();
DS18B20_WriteData(0xCC); // 跳过ROM
DS18B20_WriteData(0xBE); //读取 RAM
TempData1=DS18B20_ReadData(); //读低八位,LS Byte, RAM0
TempData2=DS18B20_ReadData(); //读高八位,MS Byte, RAM1
delay_ms(200); //延时750~900ms,保证工作周期
DS18B20_Reset();
uu=TempData2;
uu <<=8;
uu = uu|TempData1;
wendu=(uint8_t)(uu*0.00625*10+0.5);
return wendu;
}
下面展示一些 内联代码片
。
// A code block
var foo = 'bar';
// An highlighted block
#ifndef SMG_H_
#define SMG_H_
#define Max7219_pinCS_CLR P2OUT &=~BIT0
#define Max7219_pinCS_SET P2OUT |=BIT0
#define Max7219_pinCLK_CLR P2OUT &=~BIT1
#define Max7219_pinCLK_SET P2OUT |=BIT1
#define Max7219_pinDIN_CLR P2OUT &=~BIT2
#define Max7219_pinDIN_SET P2OUT |=BIT2
/* address define */
#define NO_OP 0x00
#define DIGIT0 0x01
#define DIGIT1 0x02
#define DIGIT2 0x03
#define DIGIT3 0x04
#define DIGIT4 0x05
#define DIGIT5 0x06
#define DIGIT6 0x07
#define DIGIT7 0x08
#define DECODE_MODE 0x09
#define INTENSITY 0x0A
#define SCAN_LIMIT 0x0B
#define SHUT_DOWN 0x0C
#define DISPLAY_TEST 0x0F
/**********/
void Write_Max7219(uint8_t address,uint8_t data);
void Init_Max7219_(void);
void Init_Max7219_IO(void);
#endif /* SMG_H_ */
下面展示一些 内联代码片
。
// A code block
var foo = 'bar';
// An highlighted block
#include <msp430.h>
#include "stdint.h"
#include "SMG.h"
void Write_Max7219(uint8_t address,uint8_t data)
{
uint8_t i;
Max7219_pinCS_CLR; //拉低片选线,选中器件
//发送地址
for(i=0;i<8;i++)
{
Max7219_pinCLK_CLR;
__delay_cycles(2);
if(address & 0x80){Max7219_pinDIN_SET;}
else {Max7219_pinDIN_CLR;}
__delay_cycles(2);
address=address<<1; //左移一位
Max7219_pinCLK_SET;
__delay_cycles(2);
}
//发送数据
for(i=0;i<8;i++)
{
Max7219_pinCLK_CLR;
__delay_cycles(2);
if(data & 0x80){Max7219_pinDIN_SET;}
else {Max7219_pinDIN_CLR;}
__delay_cycles(2);
data=data<<1; //左移一位
Max7219_pinCLK_SET;
__delay_cycles(2);
}
Max7219_pinCS_SET; //发送结束,上升沿锁存数据
}
void Init_Max7219_(void)
{
Write_Max7219(SHUT_DOWN,0x01); //正常工作状态
Write_Max7219(DISPLAY_TEST,0x00); //测试关
Write_Max7219(DECODE_MODE,0x00); //选用全译码模式
Write_Max7219(SCAN_LIMIT,0x07); //8只LED全用
Write_Max7219(INTENSITY,0x04); //亮度4级
}
void Init_Max7219_IO(void)
{
P2DIR |= BIT0+BIT1+BIT2; //输出模式
}
下面展示一些 内联代码片
。
// A code block
var foo = 'bar';
// An highlighted block
#include <msp430.h>
#include "stdint.h"
#include "Inital.h"
void InitSystemClock(void)
{
/*配置DCO频率为1MHZ*/
DCOCTL = CALDCO_1MHZ;
BCSCTL1 = CALBC1_1MHZ;
/*配置SMCLK的时钟源为DCO*/
BCSCTL2 &= ~SELS;
/*配置SMCLK的分频系数置为1*/
BCSCTL2 &= ~(DIVS0 | DIVS1);
}
void InitZHDIO(void)
{
P1DIR &= ~BIT1; //P1.1输入方向
P1REN |= BIT1; //使能P1.1上拉电阻
P1OUT |= BIT1; //P1.1先置高
P1IE |= BIT1; //打开P1.1中断
P1IES |= BIT1; //设定下降沿触发
P1IFG &= ~BIT1; //中断标志位清零
P1DIR &= ~BIT2; //P1.2输入方向
P1REN |= BIT2; //使能P1.2上拉电阻
P1OUT |= BIT2; //P1.2先置高
P1IE |= BIT2; //打开P1.2中断
P1IES |= BIT2; //设定下降沿触发
P1IFG &= ~BIT2; //中断标志位清零
P1DIR &= ~BIT3; //P1.3输入方向
P1REN |= BIT3; //使能P1.3上拉电阻
P1OUT |= BIT3; //P1.3先置高
P1IE |= BIT3; //打开P1.3中断
P1IES |= BIT3; //设定下降沿触发
P1IFG &= ~BIT3; //中断标志位清零
P1DIR &= ~BIT4; //P1.4输入方向
P1REN |= BIT4; //使能P1.4上拉电阻
P1OUT |= BIT4; //P1.4先置高
P1IE |= BIT4; //打开P1.4中断
P1IES |= BIT4; //设定下降沿触发
P1IFG &= ~BIT4; //中断标志位清零
P1DIR |= BIT5;
P1DIR |= BIT6;
P1DIR |= BIT7;
P2REN &= ~BIT5;
}
void InitTimer0HZD(void)
{
TA0CTL |= TASSEL_2; /*设置时钟源为SMCLK*/
TA0CCTL1 |= CAP; /*比较模式*/
TA0CTL |= MC_1; /*设置工作模式为UP*/
TA0CCR0 = 49999; //50ms 设置定时间隔
TA0CTL |= TAIE; /*开启定时器中断*/
TA0CTL &= ~TAIFG; /*清除中断标志位*/
}
void InitPWM(void)
{
TA1CTL |= TASSEL_2; /*设置时钟模式为SMCLK*/
TA1CTL |= MC0|MC1; /*UP/DOWM模式*/
TA1CCR0 = 499; /*初始值*/
TA1CCR2 = 499;
TA1CCTL0 &= ~CAP; /*设置为比较模式*/
TA1CCTL2 &= ~CAP;
TA1CCTL2 |= OUTMOD_6; /*设置比较模式6*/
P2SEL |= BIT5; /*设置I/O复用*/
P2DIR |= BIT5;
}
下面展示一些 内联代码片
。
// A code block
var foo = 'bar';
// An highlighted block
/*
* Inital.h
*
* Created on: 2020年12月1日
* Author: duwei
*/
#ifndef INITAL_H_
#define INITAL_H_
void InitSystemClock(void);
void InitZHDIO(void);
void InitTimer0HZD(void);
void InitPWM(void);
#endif /* INITAL_H_ */