#include"MSP430G2553.h"
#include "Slope.h"
#include "TCA6416A.h"
#include "HT1621.h"
#include "LCD_128.h"
#include "stdint.h"
unsigned char Key=0; //轮盘电位器的电阻等效按键值
//-----待测“传感器电阻”的分档值,实际接入了5k定值电阻+10k轮盘电位器-----
const unsigned char R_Class[8]={55,67,82,97,113,128,138,144}; //单位为百欧
void WDT_OnTime();
void Slope_R_Dect(); //测得待测电阻后的事件处理函数
void TCA6416A_LED(unsigned char num); //LED灯柱显示函数
void Display_SLOPE();
void Display_RSENS(unsigned char Rsens);
/*
* @fn: void InitUART(void)
* @brief: 初始化串口,包括设置波特率,数据位,校验位等
* @para: none
* @return: none
* @comment:初始化串口
*/
void InitUART(void)
{
/*SMCLK时钟源为DCO*/
BCSCTL2 &= ~SELS;
/*SMCLK分频系数*/
BCSCTL2 &= ~(DIVS0 | DIVS1);
/*复位USCI_Ax*/
UCA0CTL1 |= UCSWRST;
/*选择USCI_Ax为UART模式*/
UCA0CTL0 &= ~UCSYNC;
/*配置UART时钟源为SMCLK*/
UCA0CTL1 |= UCSSEL1;
/*配置波特率为9600@1MHz*/
UCA0BR0 = 0x68;
UCA0BR1 = 0x00;
UCA0MCTL = 1 << 1;
/*使能端口复用*/
P1SEL |= BIT1 + BIT2;
P1SEL2 |= BIT1 + BIT2;
/*清除复位位,使能UART*/
UCA0CTL1 &= ~UCSWRST;
}
/*
* @fn: void UARTSendString(uint8_t *pbuff,uint8_t num)
* @brief: 通过串口发送字符串
* @para: pbuff:指向要发送字符串的指针
* num:要发送的字符个数
* @return: none
* @comment:通过串口发送字符串
*/
void UARTSendString(uint8_t *pbuff,uint8_t num)
{
uint8_t cnt = 0;
for(cnt = 0;cnt < num;cnt ++)
{
while(UCA0STAT & UCBUSY);
//__delay_cycles(5000);
UCA0TXBUF = *(pbuff + cnt);
}
}
/*
* @fn: void PrintNumber(uint16_t num)
* @brief: 通过串口发送数字
* @para: num:变量
* @return: none
* @comment:通过串口发送数字
*/
void PrintNumber(uint16_t num)
{
uint8_t buff[4] = {0,0,0,'\n'};
uint8_t cnt = 0;
for(cnt = 0;cnt < 3;cnt ++)
{
buff[2 - cnt] = (uint8_t)(num % 10 + '0');
num /= 10;
}
UARTSendString(buff,4);
}
void main(void) {
WDTCTL=WDTPW+WDTHOLD;
BCSCTL1 = CALBC1_16MHZ; /* Set DCO to16MHz */
DCOCTL = CALDCO_16MHZ;
__delay_cycles(100000); //等待电压稳定
InitUART();
TCA6416A_Init();
Slope_Measure_Init();
HT1621_init();
LCD_Clear();
Display_SLOPE();
HT1621_Reflash(LCD_Buffer);
//-----设定WDT为16ms定时中断-----
WDTCTL=WDT_ADLY_16;
//-----WDT中断使能-----
IE1|=WDTIE;
_enable_interrupts();
while(1);
}
/******************************************************************************************************
* 名 称: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()
{
static unsigned int Rsens=0;
unsigned char Key_Last=0; //用于判断是否数据有更新
Key_Last=Key;
//-----通过10k参考电阻,计算电阻绝对值,单位百欧-----
Rsens=(((unsigned long int)100)*(unsigned long int)R_SENS)/R_REF;
//-----传感器电阻分档判断,5k至15k之间,分8档-----
if(Rsens<=R_Class[0]) Key=0;
else if (Rsens<=R_Class[1]) Key=1;
else if (Rsens<=R_Class[2]) Key=2;
else if (Rsens<=R_Class[3]) Key=3;
else if (Rsens<=R_Class[4]) Key=4;
else if (Rsens<=R_Class[5]) Key=5;
else if (Rsens<=R_Class[6]) Key=6;
else if(Rsens<=R_Class[7]) Key=7;
else Key=8;
//-----调用一系列显示任务-----
Display_RSENS(Rsens); //显示实际电阻值
if(!(Key==Key_Last)) //显示电阻分档值
{
LCD_DisplayDigit(LCD_DIGIT_CLEAR ,6);
LCD_DisplayDigit(Key,6);
HT1621_Reflash_Digit(6);
}
TCA6416A_LED(Key); //LED灯柱显示
}
/******************************************************************************************************
* 名 称:TCA6416A_LED()
* 功 能:根据传感器电阻值,实现LED灯柱效果
* 入口参数:无
* 出口参数:无
* 说 明:需要调用I2C和TCA6416控制LED
* 范 例:无
******************************************************************************************************/
void TCA6416A_LED(unsigned char num)
{
unsigned char i = 0;
for(i=0;i<8;i++)
{
if(i<num) // 判断当前需要点亮几盏灯
PinOUT(i,0); //根据LED接法,IO低电平为点亮LED
else
PinOUT(i,1); //根据LED接法,IO高电平为熄灭LED
}
}
/******************************************************************************************************
* 名 称:Display_SLOPE()
* 功 能:在LED上显示固定不变的内容
* 入口参数:无
* 出口参数:无
* 说 明:包括显示SLOPE,2个小数点,logo,kΩ单位。
* 范 例:无
******************************************************************************************************/
void Display_SLOPE()
{
//-----显示S-----
LCD_DisplayDigit(5,1);
//-----显示L-----
LCD_DisplayDigit(0,2);
LCD_ClearSeg(_LCD_2A);
LCD_ClearSeg(_LCD_2B);
LCD_ClearSeg(_LCD_2C);
//-----显示O-----
LCD_DisplayDigit(0,3);
//-----显示P-----
LCD_DisplayDigit(8,4);
LCD_ClearSeg(_LCD_4C);
LCD_ClearSeg(_LCD_4D);
//-----显示E-----
LCD_DisplayDigit(8,5);
LCD_ClearSeg(_LCD_5B);
LCD_ClearSeg(_LCD_5C);
//-----显示小数点-----
LCD_DisplaySeg(_LCD_DOT4);
LCD_DisplaySeg(_LCD_DOT6);
//-----显示logo-----
LCD_DisplaySeg(_LCD_TI_logo);
LCD_DisplaySeg(_LCD_QDU_logo);
//-----显示kΩ-----
LCD_DisplaySeg(_LCD_k_OHOM);
LCD_DisplaySeg(_LCD_OHOM);
}
/******************************************************************************************************
* 名 称:Display_RSENS()
* 功 能:在LED的小8字段上显示实测传感器电阻值
* 入口参数:无
* 出口参数:无
* 说 明:哪位内容有改变才更新该位的显存。
* 范 例:无
******************************************************************************************************/
void Display_RSENS(unsigned char Rsens)
{
InitUART();
unsigned char i=0;
static unsigned char Digit[3]={0};
unsigned char Digit_Past[3]={0}; //用于对比数值是否有改变
for(i=0;i<3;i++){
Digit_Past[i]=Digit[i];
}
//-----拆分数字-----
Digit[2]=Rsens/100;
Digit[1]=(Rsens%100)/10;
Digit[0]=Rsens%10;
//-----判别数位的改变,并更新该位显存-----
for(i=0;i<3;i++)
{
if(!(Digit[i]==Digit_Past[i])) //如果有变化
{
LCD_DisplayDigit(LCD_DIGIT_CLEAR ,i+8); //清除该8字段
LCD_DisplayDigit(Digit[i],i+8); //写显存映射
HT1621_Reflash_Digit(i+8); //仅更新该8字段的显存
UARTSendString(Digit,3);
}
}
}
代码中已实现将电阻值用LCD显示的功能,旋转电位器即可改变该电阻阻值,如图,只要将左上角的电阻按一定频率传输至串口调试助手即可,例如图中的9.7k欧中的9.7传输至串口调试助手,旋转电位器后又可以将新的电阻值传输至串口调试助手,请提供最终代码
#include"MSP430G2553.h"
#include "Slope.h"
#include "TCA6416A.h"
#include "HT1621.h"
#include "LCD_128.h"
#include "stdint.h"
unsigned char Key = 0; //轮盘电位器的电阻等效按键值
//-----待测“传感器电阻”的分档值,实际接入了5k定值电阻+10k轮盘电位器-----
const unsigned char R_Class[8] = { 55,67,82,97,113,128,138,144 }; //单位为百欧
void WDT_OnTime();
void Slope_R_Dect(); //测得待测电阻后的事件处理函数
void TCA6416A_LED(unsigned char num); //LED灯柱显示函数
void Display_SLOPE();
void Display_RSENS(unsigned char Rsens);
volatile int count;
volatile int adc_flag;
volatile unsigned char Digits[3];
/*
* @fn: void InitUART(void)
* @brief: 初始化串口,包括设置波特率,数据位,校验位等
* @para: none
* @return: none
* @comment:初始化串口
*/
void InitUART(void)
{
/*SMCLK时钟源为DCO*/
BCSCTL2 &= ~SELS;
/*SMCLK分频系数*/
BCSCTL2 &= ~(DIVS0 | DIVS1);
/*复位USCI_Ax*/
UCA0CTL1 |= UCSWRST;
/*选择USCI_Ax为UART模式*/
UCA0CTL0 &= ~UCSYNC;
/*配置UART时钟源为SMCLK*/
UCA0CTL1 |= UCSSEL1;
/*配置波特率为9600@1MHz*/
UCA0BR0 = 0x68;
UCA0BR1 = 0x00;
UCA0MCTL = 1 << 1;
/*使能端口复用*/
P1SEL |= BIT1 + BIT2;
P1SEL2 |= BIT1 + BIT2;
/*清除复位位,使能UART*/
UCA0CTL1 &= ~UCSWRST;
}
/*
* @fn: void UARTSendString(uint8_t *pbuff,uint8_t num)
* @brief: 通过串口发送字符串
* @para: pbuff:指向要发送字符串的指针
* num:要发送的字符个数
* @return: none
* @comment:通过串口发送字符串
*/
void UARTSendString(unsigned char* pbuff, uint8_t num)
{
uint8_t cnt = 0;
for (cnt = 0; cnt < num; cnt++)
{
while (!(IFG2 & UCA0TXIFG));
//while (UCA0STAT & UCBUSY);
//__delay_cycles(5000);
UCA0TXBUF = *(pbuff + cnt);
IFG2 &= ~UCA0TXIFG;
}
}
/*
* @fn: void PrintNumber(uint16_t num)
* @brief: 通过串口发送数字
* @para: num:变量
* @return: none
* @comment:通过串口发送数字
*/
void PrintNumber(uint16_t num)
{
uint8_t buff[4] = { 0,0,0,'\n' };
uint8_t cnt = 0;
for (cnt = 0; cnt < 3; cnt++)
{
buff[2 - cnt] = (uint8_t)(num % 10 + '0');
num /= 10;
}
UARTSendString(buff, 4);
}
void main(void) {
count = 0;
adc_flag = 0;
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 = CALBC1_16MHZ; /* Set DCO to16MHz */
DCOCTL = CALDCO_16MHZ;
__delay_cycles(100000); //等待电压稳定
InitUART();
TCA6416A_Init();
Slope_Measure_Init();
HT1621_init();
LCD_Clear();
Display_SLOPE();
HT1621_Reflash(LCD_Buffer);
//-----设定WDT为16ms定时中断-----
WDTCTL = WDT_ADLY_16;
//-----WDT中断使能-----
IE1 |= WDTIE;
_enable_interrupts();
while (1) {
if (adc_flag == 1) {
adc_flag = 0;
Digits[0] = 15;
Digits[1] = 16;
Digits[2] = 17;
//UARTSendString((uint8_t*)Digits, 3);
UCA0TXBUF = Digits[0];
UCA0TXBUF = Digits[1];
UCA0TXBUF = Digits[2];
}
}
}
/******************************************************************************************************
* 名 称:WDT_ISR(void)
* 功 能:WDT定时中断子函数
* 入口参数:无
* 出口参数:无
* 说 明:直接调用事件处理函数即可
* 范 例:无
******************************************************************************************************/
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
IE1 &= ~WDTIE;
IE1 |= WDTIE;
count++;
if (count>6)
{
count = 0;
adc_flag = 1;
}
WDT_OnTime();
}
/******************************************************************************************************
* 名 称: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()
{
static unsigned int Rsens = 0;
unsigned char Key_Last = 0; //用于判断是否数据有更新
Key_Last = Key;
//-----通过10k参考电阻,计算电阻绝对值,单位百欧-----
Rsens = (((unsigned long int)100) * (unsigned long int)R_SENS) / R_REF;
//-----传感器电阻分档判断,5k至15k之间,分8档-----
if (Rsens <= R_Class[0]) Key = 0;
else if (Rsens <= R_Class[1]) Key = 1;
else if (Rsens <= R_Class[2]) Key = 2;
else if (Rsens <= R_Class[3]) Key = 3;
else if (Rsens <= R_Class[4]) Key = 4;
else if (Rsens <= R_Class[5]) Key = 5;
else if (Rsens <= R_Class[6]) Key = 6;
else if (Rsens <= R_Class[7]) Key = 7;
else Key = 8;
//-----调用一系列显示任务-----
Display_RSENS(Rsens); //显示实际电阻值
if (!(Key == Key_Last)) //显示电阻分档值
{
LCD_DisplayDigit(LCD_DIGIT_CLEAR, 6);
LCD_DisplayDigit(Key, 6);
HT1621_Reflash_Digit(6);
}
TCA6416A_LED(Key); //LED灯柱显示
}
/******************************************************************************************************
* 名 称:TCA6416A_LED()
* 功 能:根据传感器电阻值,实现LED灯柱效果
* 入口参数:无
* 出口参数:无
* 说 明:需要调用I2C和TCA6416控制LED
* 范 例:无
******************************************************************************************************/
void TCA6416A_LED(unsigned char num)
{
unsigned char i = 0;
for (i = 0; i < 8; i++)
{
if (i < num) // 判断当前需要点亮几盏灯
PinOUT(i, 0); //根据LED接法,IO低电平为点亮LED
else
PinOUT(i, 1); //根据LED接法,IO高电平为熄灭LED
}
}
/******************************************************************************************************
* 名 称:Display_SLOPE()
* 功 能:在LED上显示固定不变的内容
* 入口参数:无
* 出口参数:无
* 说 明:包括显示SLOPE,2个小数点,logo,kΩ单位。
* 范 例:无
******************************************************************************************************/
void Display_SLOPE()
{
//-----显示S-----
LCD_DisplayDigit(5, 1);
//-----显示L-----
LCD_DisplayDigit(0, 2);
LCD_ClearSeg(_LCD_2A);
LCD_ClearSeg(_LCD_2B);
LCD_ClearSeg(_LCD_2C);
//-----显示O-----
LCD_DisplayDigit(0, 3);
//-----显示P-----
LCD_DisplayDigit(8, 4);
LCD_ClearSeg(_LCD_4C);
LCD_ClearSeg(_LCD_4D);
//-----显示E-----
LCD_DisplayDigit(8, 5);
LCD_ClearSeg(_LCD_5B);
LCD_ClearSeg(_LCD_5C);
//-----显示小数点-----
LCD_DisplaySeg(_LCD_DOT4);
LCD_DisplaySeg(_LCD_DOT6);
//-----显示logo-----
LCD_DisplaySeg(_LCD_TI_logo);
LCD_DisplaySeg(_LCD_QDU_logo);
//-----显示kΩ-----
LCD_DisplaySeg(_LCD_k_OHOM);
LCD_DisplaySeg(_LCD_OHOM);
}
/******************************************************************************************************
* 名 称:Display_RSENS()
* 功 能:在LED的小8字段上显示实测传感器电阻值
* 入口参数:无
* 出口参数:无
* 说 明:哪位内容有改变才更新该位的显存。
* 范 例:无
******************************************************************************************************/
void Display_RSENS(unsigned char Rsens)
{
InitUART();
unsigned char i = 0;
static unsigned char Digit[3] = { 0 };
unsigned char Digit_Past[3] = { 0 }; //用于对比数值是否有改变
for (i = 0; i < 3; i++) {
Digit_Past[i] = Digit[i];
}
//-----拆分数字-----
Digit[2] = Rsens / 100;
Digit[1] = (Rsens % 100) / 10;
Digit[0] = Rsens % 10;
Digits[2] = Digit[2];
Digits[1] = Digit[1];
Digits[0] = Digit[0];
//-----判别数位的改变,并更新该位显存-----
for (i = 0; i < 3; i++)
{
if (!(Digit[i] == Digit_Past[i])) //如果有变化
{
LCD_DisplayDigit(LCD_DIGIT_CLEAR, i + 8); //清除该8字段
LCD_DisplayDigit(Digit[i], i + 8); //写显存映射
HT1621_Reflash_Digit(i + 8); //仅更新该8字段的显存
}
}
}
代码看不清