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是最后电阻值
}

cpp展开代码https://docs.qq.com/sheet/DUEdqZ2lmbmR6UVdU?tab=BB08J2


本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!