//Main function main
#include
#include "key.h"
#include "lcd1602.h"
uchar Key_Flag=0;
uchar Keyval = 0;
uchar Respond_Key_Flag=0; //Response key
uchar Set_Confirm_Flag=0; //Set setting/confirmation flag
uchar Volt_buf[5]={'1','2','.','2','6'};
uchar Curr_buf[5]={'0','5','.','5' ,'4'};
void Init_port();
void Init_SysClk();
void Init_TimerB();
void key_process();
///////////////////Main function////////// /////
void main()
{
WDTCTL = WDTPW + WDTHOLD; //Turn off the watchdog
Init_port();
Init_LCD();
Init_SysClk();
Init_TimerB();
_EINT();
Disp1Char(0,0,'U ') ;
Disp1Char(1,0,':') ;
DispNChar(3,0, 5,Volt_buf);
Disp1Char(0x0F,0,'V') ;
Disp1Char(0,1,'I') ;
Disp1Char(1 ,1,':') ;
DispNChar(3,1, 5,Curr_buf);
Disp1Char(0x0F,1,'A') ;
while(1)
{
key_process();
}
}
/*******************************************
Function name: key_processFunction
: Execute tasks according to key values
Parameters: None
Return value: None
********************************************/
void key_process()
{
static uchar x=3;
uchar keyvalue;
static uchar key_one_flag=0;
keyvalue = Key_Scan();
Keyval = 0;
if(Set_Confirm_Flag == 1)
{
if(keyvalue == 1) //Set/Confirm key
{
key_one_flag ^= 1;
if(key_one_flag==1)
{
write_cmd(0x0f); //Turn on the display, display the cursor, and the character at the cursor position flashes
LocateXY(3,0); //Write the coordinate information of the display character position to the LCD
}
else
{
write_cmd(0x0c);//Turn on the display, turn off the cursor, and the character at the cursor position does not flash
Set_Confirm_Flag =0;
}
}
if((keyvalue == 2)&&( Respond_Key_Flag==1)) //short circuit key
{
Respond_Key_Flag=0;
Disp1Char(3,0,'Z');
//TACCR0 = 65535; //PWM duty cycle is set to 100%
}
if((keyvalue == 3)&&( Respond_Key_Flag==1)) //left shift
{
Respond_Key_Flag=0;
if(x >3)
{
--x;
if(x<8)
LocateXY(x,0);
else
LocateXY(x-5,1);
}
else
{
x=12;
LocateXY(x-5,1);
}
}
if((keyvalue == 4)&&( Respond_Key_Flag==1)) //right shift
{
Respond_Key_Flag=0;
if(x < 12)
{
++x;
if(x<8)
LocateXY(x,0);
else
LocateXY(x-5,1);
}
else
{
x=3;
LocateXY(x,0);
}
}
if((keyvalue == 5)&&( Respond_Key_Flag==1)) //Value "+" key
{
Respond_Key_Flag=0;
if(x<3 || x>12)
{
write_data(' ');
}
else if (x==5||x==10)
{
write_data('.') ;
if(x==5)
LocateXY(x,0);
if(x==10)
LocateXY(x-5,1);
}
else
{
if((x>=3)&&(x<=7))
{
if(Volt_buf[x-3]<'9')
Volt_buf[x-3] += 1;
else Volt_buf[x-3] ='0';
Disp1Char(x,0,Volt_buf[x-3]) ;
LocateXY(x,0);
}
else
{
if(Curr_buf[x-8]<'9')
Curr_buf[x-8] += 1;
else Curr_buf[x-8]='0';
Disp1Char(x-5,1,Curr_buf[x-8]) ;
LocateXY(x-5,1);
}
}
}
if((keyvalue == 6)&&( Respond_Key_Flag==1)) //Value "-" key
{
Respond_Key_Flag=0;
if(x<3 || x> 12)
{
write_data(' ');
}
else if(x==5||x==10)
{
write_data('.');
if(x==5)
LocateXY(x,0);
if(x= =10)
LocateXY(x-5,1);
}
else
{
if((x>=3)&&(x<=7))
{
if(Volt_buf[x-3]>'0')
Volt_buf[x-3] -= 1;
else Volt_buf[x-3]='9';
Disp1Char(x,0,Volt_buf[x-3]) ;
LocateXY (x,0);
}
else
{
if(Curr_buf[x-8]>'0')
Curr_buf[x-8] -= 1;
else Curr_buf[x-8]='9';
Disp1Char(x-5, 1,Curr_buf[x-8]) ;
LocateXY(x-5,1);
}
}
}
}
}
/*==============================================
Function name: Init_portFunction
: Initialize I/O port
Parameter: NoneReturn
value: None
=====================================================*/
void Init_port()
{
/*The following six lines of program close all IO ports*/
P1DIR = 0XFF;P1OUT = 0XFF; P2DIR = 0XFF
;P2OUT = 0XFF; P3DIR = 0XFF;
P3OUT = 0XFF;
P4DIR = 0XFF;P4OUT = 0XFF;
P5DIR = 0XFF;P5OUT = 0XFF;
P6DIR = 0XFF;P6OUT = 0XFF;
P6DIR |= BIT2;P6OUT |= BIT2; //Turn off level conversion
//Define LCD port
P4DIR = 0XFF; //Data port
P4OUT = 0;
//Define key port
P1DIR = BIT6 + BIT7; //Set P1.0~P.3 to input state, P.7 to output
}
/*==============================================
Function name: Init_SysClkFunction
: Initialize system clock
Parameter: NoneReturn
value: None
==================================================*/
void Init_SysClk()
{
unsigned int i;
BCSCTL1 &= ~XT2OFF; // XT2= HF XTAL
do
{
IFG1 &= ~OFIFG; // Clear OSCFault flag
for (i = 0xFF; i > 0; i--); // Time for flag to set
}
while ((IFG1 & OFIFG)); // OSCFault flag still set?
BCSCTL2 |= SELM_2; // MCLK = XT2 (safe), the division factor is 1
BCSCTL2 |= SELS; // SMCLK's clock source is TX2CLK, the division factor is 1
}
/*==============================================
Function name: Init_TimerBFunction
: Initialize timer B, set reference time 500usParameter
: NoneReturn
value: None
===================================================*/
void Init_TimerB()
{
TBCTL |= TBSSEL1 +TBCLR; //MCLK ,8M
TBCCTL0 = CCIE;
TBCCR0 =4000; //Timing 500us
TBCTL |= MC_1; // Start Timer_B in up mode
}
/*==============================================
Function name: TimerB_ISRFunction
: Set time interval
Parameter: NoneReturn
value: None
===================================================*/
// Timer B0 interrupt service routine
#pragma vector=TIMERB0_VECTOR
__interrupt void TimerB_ISR (void)
{
static uchar Flag_500us = 0;
Flag_500us ++;
if(Flag_500us ==20)
{
Key_Flag =1; // Timing 10ms
Flag_500us=0;
// TBCCTL0 = ~CCIE; // Turn off interrupt, used for single-step debugging, otherwise it will always be in interrupt
}
}
//Key header file key.h
#ifndef MSP430_KEY_PROCESS_H
#define MSP430_KEY_PROCESS_H
/***************************************************
Program function: Read the key values of 6 determinant buttons using timed scanning method
****************************************************/
#include
#include "lcd1602.h"
#define keyin (P1IN & 0x0F)
uchar KEY_BUFFER ;
uchar KEY_BUFFER1 ;
uchar KEY_DATA = 0x00;
uchar Num=0;
extern uchar Key_Flag;
extern uchar Keyval;
extern uchar Respond_Key_Flag;
extern uchar Set_Confirm_Flag;
/*******************************************
Function name: Delay10usFunction
: Delay about 10usParameter
: None
Return value: None
********************************************/
void Delay10us(void)
{
uint i=10;
while (i != 0)
{
i--;
}
}
/*******************************************
Function name: Key_ScanFunction
: Scan key value
Parameter: None
Return value: Keyval
********************************************/
uchar Key_Scan()
{
if(Key_Flag ==1 ) //Scan once every 10ms
{
Key_Flag =0;
//Bit processing, first use one byte to read the value of the eight-bit key, and then make a judgment
P1OUT =0X70;
Delay10us(); //Give hardware response
timeKEY_BUFFER =keyin;
KEY_BUFFER =~KEY_BUFFER;
KEY_BUFFER1 =KEY_BUFFER<<4;
P1OUT =0XB0;
Delay10us();
KEY_BUFFER =keyin;
KEY_BUFFER =~KEY_BUFFER;
KEY_BUFFER &=0X0F; //Shield the upper four bits
KEY_BUFFER1 |=KEY_BUFFER ;
if(KEY_BUFFER1 != KEY_DATA) //First determine whether a key is pressed
{
KEY_DATA =KEY_BUFFER1; //Read key value
Num =0;
}
else //KEY_BUFFER1 = KEY_DATA processing
{
Num ++;
if(Num==4) //Num=4, reading 4 times is valid, the delay reaches 40ms
{
if(KEY_DATA==0x10) //Judge key value
Keyval=1;
else if(KEY_DATA==0x20)
Keyval=2;
else if(KEY_DATA==0x40)
Keyval=3;
else if(KEY_DATA==0x80)
Keyval=4;
else if(KEY_DATA==0x01)
Keyval=5;
else if(KEY_DATA==0x02)
Keyval=6;
else Keyval=0;
}
else // Processing of Num!=4
{
if( KEY_DATA == 0x00) // Release the key, allow response
{
Num=0;
Respond_Key_Flag =1; // Key response flag
}
else //The key is not released, and it is pressed continuously
{
if((KEY_DATA == 0x10)&&(Num >=100)) //1s, determine whether it is the set/confirm key
{
Num =0;
Set_Confirm_Flag =1;
}
} }
}
}
return
Keyval;
}
#endif
//LCD 1602 header file lcd1602.h
#ifndef MSP430_LCD1602_PROCESS_H
#define MSP430_LCD1602_PROCESS_H
//Hardware connection P4 data port P3.2---EN P3.1---RW P3.0----RS
#include"msp430x14x.h"
typedef unsigned int uint;
typedef unsigned char uchar;
//Define the interface between MCU and LCD
/**************Macro definition***************/
#define Busy 0x80
#define CtrlDir P3DIR
#define CLR_RS P3OUT&=~BIT0 //RS = P3.0
#define SET_RS P3OUT|=BIT0
#define CLR_RW P3OUT&=~BIT1 //RW = P3.1
#define SET_RW P3OUT|=BIT1
#define CLR_EN P3OUT&=~BIT2 //EN = P3.2
#define SET_EN P3OUT|=BIT2
/*******************************************
Function name: Delay5ms
Function: Delay about 5ms
Parameter: None
Return value: None
********************************************/
void Delay5ms(void)
{
uint i=40000;
while (i != 0)
{
i--;
}
}
/*******************************************
Function name: WaitForEnableFunction
: Wait for 1602 LCD to complete internal operations
Parameter: None
Return value: None
********************************************/
void WaitForEnable(void)
{
P4DIR &= 0x00; //Switch P4 port to input state
CLR_RS;
SET_RW;
_NOP();
SET_EN;
_NOP();
_NOP();
while((P4IN & Busy)!=0); //Check busy flag
CLR_EN;
P4DIR |= 0xFF; //Switch P4 port to output state
}
/********************************************
Function name: write_cmdFunction
: Write command to LCD module
Parameter: com--command,
return value: none
********************************************/
void write_cmd(unsigned char com)
{
WaitForEnable(); //Wait for LCD to be unbusy
CLR_RS ; //RS=0,RW=0, write command
CLR_RW;
_NOP();
P4OUT = com;
_NOP();
SET_EN ;
_NOP();
_NOP();
CLR_EN;
}
/*******************************************
Function name: write_dataFunction
: Write display data to the current address of the LCD display
Parameter: data--display character data
Return value: None
********************************************/
void write_data(unsigned char data)
{
WaitForEnable(); //Wait for the LCD to be unbusy
SET_RS; //RS=1,RW=0, write data
CLR_RW;
_NOP();
P4OUT = data;
_NOP();
SET_EN; //Generate negative pulse
_NOP();
_NOP();
CLR_EN;
}
/*===============================================
Function name: Init_LCDFunction
: Initialize LCD
Parameters: None
Return value: None
===================================================*/
void Init_LCD()
{
CtrlDir |= 0x07; //Set the control line port to output state
P4DIR = 0xFF; //Set the data port to output state
write_cmd(0x38); //Specified reset operation
Delay5ms();
write_cmd(0x38);
Delay5ms();
write_cmd(0x38);
Delay5ms();
write_cmd(0x38); //16×2 display, 5×7 dot matrix, 8-bit data interface
write_cmd(0x08); //Turn off the display
write_cmd(0x01); //Clear the screen, data pointer = 0, all displays = 0
write_cmd(0x06); //After reading or writing a character, the address pointer increases by 1 & the cursor increases by 1, and the entire screen display does not move
write_cmd(0x0c); //Turn on the display, turn off the cursor, and the character at the cursor position does not flash
}
/*******************************************
Function name: LocateXYFunction
: Write the coordinate information of the displayed character position to the LCD
Parameters: x--column coordinate of the position
y--row coordinate of the position
Return value: None
********************************************/
void LocateXY(uchar x,uchar y)
{
uchar temp;
temp = x&0x0f;
y &= 0x01;
if(y) temp |= 0x40; //If in line 2
temp |= 0x80;
write_cmd(temp);
}
/*******************************************
Function name: Disp1CharFunction
: Display a character at a certain position
Parameters: x--column coordinate of the position
y--row coordinate of the position
data--character data to be displayed
Return value: None
********************************************/
void Disp1Char(uchar x,uchar y,uchar data)
{
LocateXY( x, y );
write_data( data );
}
/***********************************************
Function name: DispStrFunction
: Let the LCD display a string continuously from a certain position
Parameters: x--column coordinate of the position
y--row coordinate of the position
ptr--pointer to the string storage position
Return value: None
***********************************************/
void DispStr(uchar x,uchar y,uchar *ptr)
{
uchar *temp;
uchar i,n = 0;
temp = ptr;
while(*ptr++ != '\0') n++; //Calculate the number of valid characters in the string
for (i=0;i
Disp1Char(x++,y,temp[i]);
if (x == 0x0f)
{
x = 0;
y ^= 1;
}
}
}
/*******************************************
Function name: DispNcharFunction
: Let the LCD display N characters continuously from a certain position
Parameters: x--column coordinate of the position
y--row coordinate of the position
n--number of characters
ptr--pointer to the character storage position
Return value: None
********************************************/
void DispNChar(uchar x,uchar y, uchar n,uchar *ptr)
{
uchar i;
for (i=0;i
Disp1Char(x++,y,ptr[i]);
if (x == 0x0f)
{
x = 0;
y ^= 1;
}
}
}
#endif
When I first wrote it, I found that it was not very stable when I used it in practice. After two or three days of modification, I finally finalized it into the above code, which is completely usable.
Previous article:Summary of using msp430f5418
Next article:A brief discussion on the instruction cycle of MSP430 single-chip microcomputer
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- What is the difference between the on and off of a dip switch?
- "Playing with the board" + Zhou Hangci's book Chapter 6, Example 2
- STM32CubeMX uses LL library to set timer to use external clock mode to control gpio flip
- Uncle Cat's FPGA Timing Constraint Tutorial
- Where did the official website of lattice's Adder_Subtractor put its IP information? I spent the whole afternoon searching but couldn't find it.
- About the serial port receiving problem of stm32f4
- Can seneorbox calculate quaternions? --- I won't study the official documentation on my own.
- TI C6000 CCS5.5 creates DSP project
- Shanghai Hangxin ACM32F070 Development Board + Touch Function Evaluation Board Review - Chapter 5 CAN Communication
- Admin, am I demoted?