MSP430G2553 单片机口袋板,流速,流量,检测与显示
cpp/*警告:由于G2 LaunchPad上的LED2使用了P1.6(I2C引脚),所以所有涉及到I2C的实验都必须把P1.6跳线拔除,包含本例程!
* main.c
*/
#include"MSP430G2553.h"
#include "Slope.h"
#include "TCA6416A.h"
#include "HT1621.h"
#include "LCD_128.h"
#define CPU_F ( (double) 16000000)
#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 u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
unsigned int Rsens = 0; //最后电阻值
int xianshi_choose = 0;
u32 leijiliang = 0;
u32 liusu = 0;
void WDT_OnTime();
void Slope_R_Dect(); //测得待测电阻后的事件处理函数
/* 显示一个数字 */
void dis_num_6( u32 num) {
unsigned char bua;
bua = num % 1000000 / 100000;
LCD_DisplayDigit(bua, 1);
bua = num % 100000 / 10000;
LCD_DisplayDigit(bua, 2);
bua = num % 10000 / 1000;
LCD_DisplayDigit(bua, 3);
bua = num % 1000 / 100;
LCD_DisplayDigit(bua, 4);
bua = num % 100 / 10;
LCD_DisplayDigit(bua, 5);
bua = num % 10;
LCD_DisplayDigit(bua, 6);
//LCD_DisplaySeg(i);
LCD_DisplaySeg(_LCD_DOT4);
HT1621_Reflash(LCD_Buffer);
}
/* 检测按键函数 */
void I2C_IODect() /* 检测事件确实发生了 */
{
static unsigned char KEY_Past = 0, KEY_Now = 0;
KEY_Past = KEY_Now;
/* ----判断I2C_IO10所连的KEY1按键是否被按下------ */
if ((TCA6416A_InputBuffer & BIT8) == BIT8)
KEY_Now |= BIT0;
else
KEY_Now &= ~BIT0;
if (((KEY_Past & BIT0) == BIT0) && (KEY_Now & BIT0) != BIT0) {
/*按键1 事件 */
xianshi_choose = 0;
//改变xianshi_choose变量 主程序里 显示会切换
}
/* ----判断I2C_IO11所连的KEY2按键是否被按下------ */
if ((TCA6416A_InputBuffer & BIT9) == BIT9)
KEY_Now |= BIT1;
else
KEY_Now &= ~BIT1;
if (((KEY_Past & BIT1) == BIT1) && (KEY_Now & BIT1) != BIT1) {
/*按键2 事件 */
xianshi_choose = 1;
}
/* ----判断I2C_IO12所连的KEY3按键是否被按下------ */
if ((TCA6416A_InputBuffer & BITA) == BITA)
KEY_Now |= BIT2;
else
KEY_Now &= ~BIT2;
if (((KEY_Past & BIT2) == BIT2) && (KEY_Now & BIT2) == 0) {
/*按键3 事件 */
}
/* ----判断I2C_IO13所连的KEY4按键是否被按下------ */
if ((TCA6416A_InputBuffer & BITB) == BITB)
KEY_Now |= BIT3;
else
KEY_Now &= ~BIT3;
if (((KEY_Past & BIT3) == BIT3) && (KEY_Now & BIT3) == 0) {
/*按键4 事件 */
}
}
//串口发送单一字符
void sendan(unsigned char zifu) {
while (!(IFG2 & UCA0TXIFG))
; // USCI_A0 TX buffer ready?
UCA0TXBUF = zifu; // TX -> RXed character
}
//串口发送字符串
void send_string(unsigned char *s) {
while ((*s) != '\0') {
sendan(*s);
s++;
}
}
//串口发送流量或者累积量
void send_liuliang_andleiji() {
unsigned char bua;
unsigned char zifuchuan[30];
unsigned char countaa = 0;
zifuchuan[countaa++] = liusu % 1000000 / 100000 + '0';
zifuchuan[countaa++] = liusu % 100000 / 10000 + '0';
zifuchuan[countaa++] = liusu % 10000 / 1000 + '0';
zifuchuan[countaa++] = liusu % 1000 / 100 + '0';
zifuchuan[countaa++] = liusu % 100 / 10 + '0';
zifuchuan[countaa++] = '.';
zifuchuan[countaa++] = liusu % 10 + '0';
zifuchuan[countaa++] = 'L';
zifuchuan[countaa++] = '/';
zifuchuan[countaa++] = 'S';
zifuchuan[countaa++] = ' ';
zifuchuan[countaa++] = ' ';
zifuchuan[countaa++] = leijiliang % 1000000 / 100000 + '0';
zifuchuan[countaa++] = leijiliang % 100000 / 10000 + '0';
zifuchuan[countaa++] = leijiliang % 10000 / 1000 + '0';
zifuchuan[countaa++] = leijiliang % 1000 / 100 + '0';
zifuchuan[countaa++] = leijiliang % 100 / 10 + '0';
zifuchuan[countaa++] = '.';
zifuchuan[countaa++] = leijiliang % 10 + '0';
zifuchuan[countaa++] = 'L';
send_string(zifuchuan);
send_string("\r\n");
}
void main(void) {
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 = CALBC1_16MHZ; /* Set DCO to16MHz */
DCOCTL = CALDCO_16MHZ;
__delay_cycles(100000); //等待电压稳定
TCA6416A_Init();
Slope_Measure_Init();
HT1621_init();
/* ----提示初始化成功---- */
PinOUT(0, 1); /* 指定0号管脚输出为0 */
PinOUT(1, 1); /* 指定1号管脚输出为0 */
PinOUT(2, 1); /* 指定0号管脚输出为0 */
PinOUT(3, 1); /* 指定1号管脚输出为0 */
PinOUT(4, 1); /* 指定0号管脚输出为0 */
PinOUT(5, 1); /* 指定1号管脚输出为0 */
PinOUT(6, 1); /* 指定0号管脚输出为0 */
PinOUT(7, 1); /* 指定1号管脚输出为0 */
LCD_Clear();
//-----设定WDT为16ms定时中断-----
WDTCTL = WDT_ADLY_16;
//-----WDT中断使能-----
IE1 |= WDTIE;
TA1CCTL0 = CCIE;
TA1CCR0 = 3276 / 5; /* 20MS */
TA1CTL = TASSEL_1 + MC_1; //up to CCR0
//串口设置
// P1DIR |= BIT2;
// P1SEL = BIT1 + BIT2; // P1.1 = RXD, P1.2=TXD
// P1SEL2 = BIT1 + BIT2; // P1.1 = RXD, P1.2=TXD
// UCA0CTL1 |= UCSSEL_1; // CLK = ACLK
// UCA0BR0 = 0x03; // 32kHz/9600 = 3.41
// UCA0BR1 = 0x00; //
// UCA0MCTL = UCBRS1 + UCBRS0; // Modulation UCBRSx = 3
// UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
//IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
_enable_interrupts();
while (1) {
PinIN();
I2C_IODect(); /*按键检测处理 */
TA1CTL = TASSEL_1 + MC_1 + TACLR; /* 打开定时器 */
LPM0;
}
}
// Echo back RXed character, confirm TX buffer is ready first
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void) {
while (!(IFG2 & UCA0TXIFG))
; // USCI_A0 TX buffer ready?
UCA0TXBUF = UCA0RXBUF; // TX -> RXed character
}
/* Timer A0 interrupt service routine */
#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer1_A(void) {
//更新流速和累积量 每一秒钟来一次
static float bufa;
static unsigned char countasdf = 0;
countasdf++;
if (countasdf == 50) {
countasdf=0;
if (Rsens != 0) {
bufa = (float) Rsens * 2.2; //Rsens是拨码电阻值 2.2是系数 随便设置的 主要是得到流速
}
liusu = bufa * 10; //因为要保留1位小数 乘以10 显示到LED后有小数
leijiliang += liusu; //每一秒的流速单位就是 L/S 一秒算多少升 加到累积量上
if (leijiliang > 100000) {
leijiliang = 0;
}
if (xianshi_choose == 0) {
//xianshi_choose=0 显示流速 否则显示累积量
dis_num_6(liusu);
} else {
dis_num_6(leijiliang);
}
//send_liuliang_andleiji();//串口发送流量和累积量
}
TA1CTL = TASSEL_1 + MC_0 + TACLR; /* 停下时钟 */
LPM0_EXIT;
}
/******************************************************************************************************
* 名 称:WDT_ISR(void)
* 功 能:WDT定时中断子函数
* 入口参数:无
* 出口参数:无
* 说 明:直接调用事件处理函数即可
* 范 例:无
******************************************************************************************************/
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void) {
IE1 &= ~WDTIE;
WDT_OnTime();
IE1 |= WDTIE;
}
/******************************************************************************************************
* 名 称:WDT_OnTime()
* 功 能:WDT定时中断的事件处理函数
* 入口参数:无
* 出口参数:无
* 说 明:主要工作都在事件处理函数中体现
* 范 例:无
******************************************************************************************************/
void WDT_OnTime() {
static unsigned char Charge_Ready = 0; //充满电标志位
static unsigned char REF_Mreasure_Ready = 0; //等于8表明参考电阻已测完
static unsigned long R_REF_Sum = 0; //暂存参考电阻的累加值
if (Charge_Ready == 0) //未充满电
{
Slope_Port_Charge(); //充电
Slope_R_Dect(); //执行显示LED的任务
Charge_Ready = 1; //充满电标志
} else {
//-----测量8次参考电阻值-----
if (REF_Mreasure_Ready < 8) // 判断是否继续测量参考电阻值
{
Slope_Measure_REF(); //测参考电阻值
R_REF_Sum = R_REF_Sum + R_REF; //累加电阻值
if (REF_Mreasure_Ready == 7)
R_REF = R_REF_Sum >> 3; //测量完毕求出参考电阻的平均值
REF_Mreasure_Ready++; //测量次数累加
}
//-----得到参考电阻值后,开始不停的测量传感器电阻值-----
else
Slope_Measure_SENS(); //测完参考电阻才测传感器电阻
Charge_Ready = 0; //测完一次,又该充电了
}
}
/******************************************************************************************************
* 名 称:Slope_R_Dect()
* 功 能:对传感器电阻判断档位,调用LED显示程序
* 入口参数:无
* 出口参数:无
* 说 明:主要工作都在事件处理函数中体现
* 范 例:无
******************************************************************************************************/
void Slope_R_Dect() {
//-----通过10k参考电阻,计算电阻绝对值,单位百欧-----
Rsens = (((unsigned long int) 100) * (unsigned long int) R_SENS) / R_REF;
//Rsens是最后电阻值
}
cpphttps://docs.qq.com/sheet/DUEdqZ2lmbmR6UVdU?tab=BB08J2
本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!