Entry parameter description:
// control port
//#define SET_RS sbi(PORTB,5)
//#define CLR_RS cbi(PORTB,5)
//#define OUT_RS sbi(DDRB,5)
//#define SET_RW sbi(PORTB,6)
//#define CLR_RW cbi(PORTB,6)
//#define OUT_RW sbi(DDRB,6)
//#define SET_E sbi(PORTB,7)
//#define CLR_E cbi(PORTB,7)
//#define OUT_E sbi(DDRB,7)
// data port
//#define SET_D4 sbi(PORTD,4)
//#define CLR_D4 cbi(PORTD,4)
//#define OUT_D4 sbi(DDRD,4)
//#define SET_D5 sbi(PORTD,5)
//#define CLR_D5 cbi(PORTD,5)
//#define OUT_D5 sbi(DDRD,5)
//#define SET_D6 sbi(PORTD,6)
//#define CLR_D6 cbi(PORTD,6)
//#define OUT_D6 sbi(DDRD,6)
//#define SET_D7 sbi(PORTD,7)
//#define CLR_D7 cbi(PORTD,7)
//#define OUT_D7 sbi(DDRD,7)
// busy port
//#define GET_BF gbi(PIND,7)
//#define OUT_BF sbi(DDRD,7)
//#define IN_BF cbi(DDRD,7)
----------------------------------------------------------------------
接口定义:
LCD1602 ATmega16
1.GND -------- GND
2.VCC -------- VCC
3.V0 -------- V0
4.RS -------- 由外部程序定义
5.R/W -------- 由外部程序定义
6.E -------- 由外部程序定义
7.D0 -------- NC
8.D1 -------- NC
9.D2 -------- NC
10.D3 -------- NC
11.D4 -------- 由外部程序定义
12.D5 -------- 由外部程序定义
13.D6 -------- 由外部程序定义
14.D7 -------- 由外部程序定义
15.LED+ -------- VCC
16.LED- -------- GND
说明:
(1)使用ATmega16的7根IO口操作LCD1602
(2)该程序的优点是:7根IO可任意定义,不需分布在固定的一组PORT口上
(3)该程序的缺点是:IO定义的写法较为繁琐
----------------------------------------------------------------------
待定参数说明:
//#define DELAY() {_nop_();_nop_();_nop_();}
----------------------------------------------------------------------
对外变量说明:
----------------------------------------------------------------------
对外函数说明:
----------------------------------------------------------------------
10101010101010101010101010101010101010101010101010101010101010101010*/
#ifndef LCD1602_H
#define LCD1602_H
#include "D:\ICC_H\CmmICC.H"
/* 待定参数 */
#define DELAY() {NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();}
/* Writing without considering portability */
//uint8 bdata bdat;
//sbit bdat0=bdat^0;
//sbit bdat1=bdat^1;
//sbit bdat2=bdat^2;
//sbit bdat3=bdat^ 3;
//sbit bdat4=bdat^4;
//sbit bdat5=bdat^5;
//sbit bdat6=bdat^6;
//sbit bdat7=bdat^7;
/* Writing method considering portability */
uint8 bdat;
#define bdat0 (bdat&0x01)
#define bdat1 (bdat&0x02)
#define bdat2 (bdat&0x04)
#define bdat3 (bdat&0x08)
#define bdat4 (bdat&0x10)
#define bdat5 (bdat&0x20)
#define bdat6 (bdat&0x40)
#define bdat7 (bdat&0x80)
#define CGRAM0 0x00
#define CGRAM1 0x01
#define CGRAM2 0x02
#define CGRAM3 0x03
#define CGRAM4 0x04
#define CGRAM5 0x05
#define CGRAM6 0x06
#define CGRAM7 0x07
#define TRUE 1
#define FALSE 0
bool LCD1602Err = FALSE;
/*-------------------------------------- ------------------------------
Function name: LCD1602 read read read read busy ~
Function function: It is said to be read read read Reading is busy~
Note: For high-speed CPU, delay should be added, it seems to be nonsense~
Prompt description: No
input:
Return: None
-------------------- ------------------------------------------------*/
void busy(void)
{
uint16 busyCounter=0;
bool busySta; //used to detect LCD busy status
IN_BF;
SET_D4;
SET_D5;
SET_D6;
SET_D7;
DELAY();
CLR_RS;
DELAY();
SET_RW;
DELAY();
do
{
SET_E;
DELAY() ;
/* Read the values of AC4-AC6 and BF here. The program does not need to record the values of AC4-AC6, so they are not stored. */
busySta=(bool)GET_BF;
CLR_E;
DELAY();
/* Read "BUSY" When the "D4-D7" state may have changed, it must be set to output "1" again */
SET_D4;
SET_D5;
SET_D6;
SET_D7;
DELAY();
SET_E;
DELAY();
/* Here, the AC0-AC3 bits are read Value, the program does not need to record the value of AC0-AC3, so it is not stored*/
CLR_E;
DELAY();
if(busyCounter==1000)
{
LCD1602Err=TRUE; //Mark LCD1602 error, convenient for reporting error to system
return; //Avoid program blocking due to LCD1602 error
}
busyCounter++;
}
while(busySta);
LCD1602Err =FALSE;
CLR_E;
OUT_BF;
}
/*---------------------------------------- ----------------------------
Function name: LCD1602 write operation
function function:
Note: For high-speed CPU, delay should be added, which seems to be nonsense~
Hint: No
input:
Return: None
--------------------------------------------------------------------*/
void write(bool flag,uint8 dat) //flag=0:command,flag=1:data
{
bdat=dat;
busy();
if(flag)
SET_RS;
else
CLR_RS;
DELAY();
CLR_RW;
DELAY();
if(bdat4)
SET_D4;
else
CLR_D4;
if(bdat5)
SET_D5;
else
CLR_D5;
if(bdat6 )
SET_D6;
else
CLR_D6;
if(bdat7)
SET_D7;
else
CLR_D7;
DELAY();
SET_E;
DELAY();
CLR_E;
DELAY();
if(bdat0)
SET_D4;
else
CLR_D4;
if(bdat1)
SET_D5;
else
CLR_D5;
if(bdat2)
SET_D6;
else
CLR_D6;
if(bdat3)
SET_D7;
else
CLR_D7;
DELAY();
SET_E;
DELAY();
CLR_E;
DELAY();
}
/*------------------------------------------------------------------------------------
Function name: LCD1602 read operation
Function function:
Note: For high-speed CPU, a delay should be added. It seems to be nonsense.
Tip description: No
input:
Return: None
--------------------------------------------------------------------*/
//void read(uint8 adr)
//{
//}
/*--------------------------------------------------------------------
Function name: LCD1602 sets CGRAM content
Function function:
Note: For high-speed CPU, a delay should be added. It seems to be nonsense.
Tip description: Call LCD1602_setCG(0,userCh) to write the user-defined character "userCh"
input Input: "adr" data range: 0-8, "buf" is the character "userCh" that the user needs to write
Return: None
-------------------------------------------------------------------------------------*/
void LCD1602_setCGRAM(uint8 adr,const uint8 buf[8])
{
uint8 i;
write(0,0x40+adr*8);
for(i=0;i<8;i++)
write(1,buf[i]);
/* The following writing method must not be sampled, because the input is an array and the last one is not '\0' */
//while(*buf)
//write(1,*buf++);
}
/*--------------------------------------------------------------------
Function name: LCD1602 command setting
function Function:
Note: For high-speed CPU, a delay should be added. It seems to be nonsense~
Tips:
输 入:"CLR_SCR"/"GO_HOME"/"AC_INC"/"AC_DEC"...
返 回:无
--------------------------------------------------------------------*/
//---- function ------ 1 -------- 0 ----LcdWordPos--
// dispEn | Enable | DISAble | bit2
// cursorEn | Enable | Disable | bit1
// blinkEn | Enable | Disable | bit0
//------------------------------------------------------
// isACinc | INC_AC | DEC_AC | bit1
// shiftEn | Enable | Disable | bit0
//------------------------------------------------------
void LCD1602_setCmd(uint8 *str)
{
static bool dispEn =0;
static bool cursorEn=0;
static bool blinkEn =0;
static bool shiftEn =0;
static bool isACinc =0;
if(!strcmp(str,"CLR_SCR")) //clear screen
write(0,0x01);
else if(!strcmp(str,"GO_HOME")) //set AC go home
write(0,0x02);
/*--------------------------------------------------
isACinc & shiftEn 共用一个命令设置
--------------------------------------------------*/
else if(!strcmp(str,"INC_AC")) //set AC as inc mode
{
isACinc=1;
if(shiftEn)
write(0,0x07);
else
write(0,0x06);
}
else if(!strcmp(str,"DEC_AC")) //set AC as dec mode
{
isACinc=0;
if(shiftEn)
write(0,0x05);
else
write(0,0x04);
}
else if(!strcmp(str,"EN_SHIFT")) //enable shift
{
shiftEn=1;
if(isACinc)
write(0,0x07);
else
write(0,0x06);
}
else if(!strcmp(str,"DIS_SHIFT")) //disable shift
{
shiftEn=0;
if(isACinc)
write(0,0x05);
else
write(0,0x04);
}
/*--------------------------------------------------
dispEn & cursorEn & blinkEn共用一个命令设置
--------------------------------------------------*/
else if(!strcmp(str,"OPEN_LCD")) //opern lcd
{
dispEn=1;
if(cursorEn)
if(blinkEn)
write(0,0x0F);
else
write(0,0x0E);
else
if(blinkEn)
write(0,0x0D);
else
write(0,0x0C);
}
else if(!strcmp(str,"CLOSE_LCD")) //close lcd
{
dispEn=0;
if(cursorEn)
if(blinkEn)
write(0,0x0B);
else
write(0,0x0A);
else
if(blinkEn)
write(0,0x09);
else
write(0,0x08);
}
else if(!strcmp(str,"OPEN_CURS")) //open cursor
{
cursorEn=1;
if(dispEn)
if(blinkEn)
write(0,0x0F);
else
write(0,0x0E);
else
if(blinkEn)
write(0,0x0B);
else
write(0,0x0A);
}
else if(!strcmp(str,"CLOSE_CURS")) //close cursor
{
cursorEn=0;
if(dispEn)
if(blinkEn)
write(0,0x0D);
else
write(0,0x0C);
else
if(blinkEn)
write(0,0x09);
else
write(0,0x08);
}
else if(!strcmp(str,"EN_BLINK")) //enable blink cursor
{
blinkEn=1;
if(dispEn)
if(cursorEn)
write(0,0x0F);
else
write(0,0x0D);
else
if(cursorEn)
write(0,0x0B);
else
write(0,0x09);
}
else if(!strcmp(str,"DIS_BLINK")) //disable blink cursor
{
blinkEn=0;
if(dispEn)
if(cursorEn)
write(0,0x0E);
else
write(0,0x0C);
else
if(cursorEn)
write(0,0x0A);
else
write(0,0x08);
}
/*--------------------------------------------------
dispEn & cursorEn & blinkEn共用一个命令设置
--------------------------------------------------*/
else if(!strcmp(str,"RIGHT_SCR")) //right shift screen
write(0,0x1c);
else if(!strcmp(str,"LEFT_SCR")) //left shift screen
write(0,0x18);
else if(!strcmp(str,"RIGHT_CURS")) //right shift cursor
write(0,0x14);
else if(!strcmp(str,"LEFT_CURS")) //left shift cursor
write(0,0x10);
}
/*--------------------------------------------------------------------
Function name: LCD1602 initialization
function function:
Note:
Tip description: No
input:
Return: None
--------------------------------------------------------------------*/
void LCD1602_init(void)
{
OUT_RS;
OUT_RW;
OUT_E;
OUT_D4;
OUT_D5;
OUT_D6;
OUT_D7;
delay50ms(1);
CLR_D7;
CLR_D6;
SET_D5;
SET_D4;
DELAY();
CLR_RS;
DELAY();
CLR_RW;
SET_E;
DELAY(); CLR_E
;
delay50us(200);
SET_E; DELAY ( ); CLR_E; delay50us (200); SET_E ; D5 ; CLR_D4 ; DELAY(); SET_E; DELAY(); CLR_E ; DELAY(); LCD1602_setCmd("OPEN_LCD"); LCD1602_setCmd("CLR_SCR"); LCD1602_setCmd("INC_AC"); //LCD1602_setCmd("OPEN_CURS"); //LCD1602_set Cmd("GO_HOME"); } /*-------------------------------------------------------------------- Macro name: Set AC value Macro function: Set AC value Notes: Tip Description: Input: Return: None --------------------------------------------------------------------*/ #define LCD1602_setAC(adr) write(0,adr) /*-------------------------------------------------------------------- Function name: Output a character Function function: Notes: For high-speed CPU, delay should be added, which seems to be nonsense~ Tip Description: Call LCD1602_putc(0x80,'A'), then output 'A' at the first character of the first line Input : Return: None --------------------------------------------------------------------*/ void LCD1602_putc(uint8 adr,uint8 ch) { write(0,adr); write(1,ch); }
/*--------------------------------------------------------------------
Function name: Output a string
Function:
Note: No
prompt Description: Call LCD1602_puts(0x80,"waveShare"), then output "waveShare" from the first position of the first line Input
:
Return: None
--------------------------------------------------------------------*/
void LCD1602_puts(uint8 startAdr,uint8 *str)
{
/*
while(*str)
{
LCD1602_putc(addr++,*str++);
}
*/
//LCD1602_setCmd("AC++");
write(0,startAdr);
while(*str)
write(1,*str++);
}
/*--------------------------------------------------------------------
Function name: Output a value (with 0)
Function function: Sometimes you may not need "123", but "00123"
Note: No
prompt Description: Call LCD1602_putd0(0x8F,123,5), then output "00123" from 0x8B to 0X8F
Input:
Return: None
--------------------------------------------------------------------*/
//for example:dat=123,length=6,output 000123
void LCD1602_putd0(uint8 endAdr,uint32 dat,uint8 length)
{
sint8 i;
speaData(dat,length);
//LCD1602_setCmd("AC++");
write(0,endAdr-length+1);
for(i=length-1;i>=0;i--)
write(1,dataElem[i]+0x30);
}
/*--------------------------------------------------------------------
Function name: Output a value (without 0)
Function function:
Note: No
prompt Description: Call LCD1602_putd(0x8F,123,5), then output "123" from 0x8B to 0X8F Input
:
Return: None
--------------------------------------------------------------------*/
void LCD1602_putd(uint8 endAdr,uint32 dat,uint8 length)
{
sint8 i;
sint8 effectLen;
if(dat>999999)
effectLen=7;
else if(dat>99999)
effectLen=6;
else if(dat>9999)
effectLen=5;
else if(dat>999)
effectLen=4;
else if(dat>99)
effectLen=3;
else if(dat>9)
effectLen=2;
else
effectLen=1;
speaData(dat,effectLen);
//LCD1602_setCmd("AC++");
if(length>effectLen)
{
write(0,endAdr-length+1);
for(i=length-effectLen-1;i>=0;i--)
write(1,' ');
}
for(i=effectLen-1;i>=0;i--)
{
if(i==0||dataElem[i])
{
write(0, endAdr-i);
for(;i>=0;i--)
write(1,dataElem[i]+0x30);
}
}
}
/*--------------------------------------------------------------------
Function name: Output a mixed string
Function function:
Note: It is best not to load this function, because it will take up nearly 1K space
Tips: Call LCD1602_sprintf(0x8F,12AB,4), then output "12ABok" from 0x8B to 0X8F
Input:
Return: None
--------------------------------------------------------------------*/
//void LCD1602_sprintf(uint8 startAdr,uint32 dat,uint8 length)
//{
// /* clear the display area first here! */
// //LCD1602_puts(addr," ");
// sprintf(t,"%luok",dat);
// //LCD1602_setCmd("AC++");
// LCD1602_puts(addr,t);
//}
#endif
Previous article:AVR MCU serial port multi-machine communication program
Next article:AVR multi-machine communication
Recommended ReadingLatest update time:2024-11-15 23:42
- Popular Resources
- Popular amplifiers
- Single-chip microcomputer C language programming and simulation
- 100 Examples of Microcontroller C Language Applications (with CD-ROM, 3rd Edition) (Wang Huiliang, Wang Dongfeng, Dong Guanqiang)
- Principles and Applications of Single Chip Microcomputers 3rd Edition (Zhang Yigang)
- Principles and Applications of Single Chip Microcomputers and C51 Programming (3rd Edition) (Xie Weicheng, Yang Jiaguo)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- 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
- Network Analyzer Tests RLC Series Network
- 【Beijing】Recruiting embedded (video direction) R&D engineers
- UART interface algorithm transplantation encryption chip debugging skills - communication debugging
- Free sharing video - introduction to common electronic components such as resistors, capacitors and inductors------------The key is free
- MicroPython adds lightsleep() functionality to STM32
- Have you watched "Avengers 4"?
- TI CC2540 USB CDC Serial Port driver installation failure reasons and solutions
- TMS320DM642 learning connection method
- How to copy the files used in the compiler and IDE installation directory to the project folder when creating a new CCS project
- Puzhong 89C52, burning program error