STM32F072RB 实作笔记(七)- LCD 1602 的使用

STM32F072RB 模拟板,本身没有显示器,如果能加装一个,那么在实验的时候可以监看程式进行状态就方便许多了。于是我就用手边的 LCD 1602,做一个试试!以下就是整个过程。

LCD1602 规格資料

LCD1602 是一个非常普遍的材料,规格同一,书面資料也是相互抄袭,从网络上很轻易的就能找到,我这里附上的是英文的資料,中文資料可以自己再去找找。
LCD 1602 硬件长相
LCD 1602 硬件长相
接脚定义
请添加图片描述
一个很重要的指令表
写程式的时候会一直参考这个表格,特别要注意 RS 和 R/W 这两个脚位的讯号变化。
请添加图片描述
各个指令的说明
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
编写属于 LCD1602 的 command 档
我依照 LCD 1602 的指令规定,逐个编写指令放置在 LCD1602_cmd.c 的档案里。内容包刮 F072BR 的接脚定义,以下列了几个觉得是重要的:
a. void GPIO_Configuration(void);// 设定GPIOC 和 GPIOB 的脚位定义;
b. void GPIO_Write(u8 temp); //写(输出讯号时候)脚位要重新定义;
c. void LCD1602_Init(void);// 执行 LCD1602 重置的动作-- 注意要适度的加入Delay()。
d. u8 LCD_CheckBusy(void);// 这一个功能是 最常使用的功能。因为要常常检查LCD是不是在忙碌状态。传回的資料还附带了LCD游标的目前位置,所以设成U8, 传回一个 byte 的 地址。
e. void LCD1602_SetCursor( u8 x, u8 line );//加上line 位置的cursor 设定.
f. void GPIOB_SetBits(u8 GPIOB_Pin); 和
void GPIOB_ResetBits(u8 GPIOB_Pin); 是为了方便 header 档加上的。
g. 其他的因为很简单,有兴趣自己对照以下就看得懂,也可以自己改一改。 以下就是 LCD1602_cmd.c 的代码。

#include "lcd1602.h"  
#include "stm32f0xx.h"          // File name depends on device used

//---------------------------------
 void GPIO_Configuration(void)
 {      //------------GPIOC0_7_init(void)      --define  Port C, pin 0~7
	RCC->AHBENR |= 0x1ul<<19;    // set GPIOC on
	GPIOC->MODER &= ~(0xfffful);   //clear MODER
	GPIOC->MODER |= 0x5555ul;      //set Moder to bx0101 -->output
	GPIOC->OSPEEDR &= ~0xfffful;	// clear OSPEEDR
	GPIOC->OSPEEDR |= 0x5555ul;		// set OSPEEDR to bx0101 medium speed

//-------------------void GPIOB0_2_init(void)      --define  Port B, pin 0~2
//GPIOC->OTYPER &= ~(0x1ul<<7);    // GPIOC to OC
	RCC->AHBENR |= 0x1ul<<18;    // set GPIOC on
	GPIOB->MODER &= ~(0x3ful);   //clear MODER
	GPIOB->MODER |= 0x15ul;      //set Moder to bx0101 -->output
	GPIOB->OSPEEDR &= ~0x3ful;	// clear OSPEEDR
	GPIOB->OSPEEDR |= 0x15ul;		// set OSPEEDR to bx0101 medium speed
	
}
 //------------------------------------
u8 GPIO_ReadAddr(u8 temp){
	LCD_RS_H();    //=0;
    LCD_RW_H();    //=1;
	GPIOC->MODER |= 0x2ul <<7;       //set GPIOC bit 7 Moder to bx11 -->intput
    temp = GPIOC->IDR  ;
	return temp;
 }
 
//--------------------------------------------
 void GPIO_Write(u8 temp){
 	GPIOC->MODER &= ~(0xfffful);   //clear MODER
	GPIOC->MODER |= 0x5555ul;      //set Moder to bx0101 -->output
	GPIOC->ODR = temp;
 }
 
//--------------------------------------------
 void LCD_delay(u32 x){
	u32 i, j;
	for(i=0; i<x; i++){for(j=0; j<1000; j++) ;
	}
	
}
//-------------------------------
 void LCD1602_Init()
{
	LCD1602_ClearScreen();
	LCD_delay(41);
	func_set(1,1,0);   //0x28 DL=1(8-bit), N=0(1-line), F=1(5x11)
	LCD_delay(41);

	LCD_delay(5);
	LCD_entry_mod(1, 0);    // ID =1,  SH=0
	LCD_delay(5);
	cusr_ctrl(1,1,1);      // Dp =1, csr =1, blk =1
}

  
 //------------------------------------
 
 u8 LCD_CheckBusy(void)
{
  u8 sta;
    LCD_RS_L();    //=0;
    LCD_RW_H();    //=1;
	GPIOC->MODER &= ~(0xfffful);   //clear MODER
	GPIOC->MODER |= 0xaaaaul;      //set Moder to bx1010 -->input
    do{
        LCD_EN_H();   // =1;
        LCD_delay(5);
        sta = (GPIOC ->IDR);
        LCD_EN_L();   // =0;
    }while(sta & 0x80);   //BF=1, LCD is busy
	 return sta;
}
 //------------------------------------
 
 void LCD1602_WriteCmd( u8 cmd )
  {
  	u8 addr = LCD_CheckBusy(); //to get cursor address
    LCD_RS_L();   //LCD_RS = 0;
    LCD_RW_L();   //LCD_RW = 0;
    GPIO_Write(cmd);   // GPIO_OutData(Cmd);    
    LCD_EN_H();    // = 1;
    LCD_delay(5);
    LCD_EN_L();    // = 0;     
 }
 //------------------------------------
 
 void LCD1602_WriteData( u8 data )
  {
    u8 addr = LCD_CheckBusy(); //o get cursor address
    LCD_RS_H();    //=1;
    LCD_RW_L();    //=0;
    GPIO_Write( data);      // GPIO_OutData(Dat);
    LCD_EN_H();    //=1;
    LCD_delay(5);
    LCD_EN_L();     //EN = 0;
 }
 
 //------------------------------------
 
 void LCD1602_SetCursor( u8 x, u8 line )
  {
    u8 addr;
    if (line == 0)  addr = 0x00 + x;
    if (line == 1)  addr = 0x40 + x;
    LCD1602_WriteCmd(addr | 0x80);
 }
 //------------------------------------
 
 void LCD1602_Show_Str( u8 x, u8 y, u8 *str )
  { 
	u16 count =0;
    LCD1602_SetCursor(x, y);

    while(*str != '\0')
    {  
      LCD1602_WriteData(*str++); count++;
	  if (count>15){LCD1602_SetCursor(0, 0x40ul);}
    }
 }
 //------------------------------------
 
 void LCD1602_DisNumber(u8 x,u8 y, u8 Num)  //change line check
{
    LCD1602_SetCursor(x,y);
    LCD1602_WriteData(0x30+Num/10);
    LCD1602_SetCursor(x+1, y);
    LCD1602_WriteData(0x30+Num%10);
}
//-------------------------------------
void LCD1602_DisChar(u8 x, u8 y, u8 ch)
{
    LCD1602_SetCursor(x, y);        //set curcor to upper or lower line
    LCD1602_WriteData(ch);
}
//------------------------------------
//RS ->PB0, Rw ->PB1, EN ->PB2
void GPIOB_SetBits(u8 GPIOB_Pin)
{
	GPIOB->ODR |= 0x1ul <<GPIOB_Pin;  //set to 1
}
//------------------------------------
void GPIOB_ResetBits(u8 GPIOB_Pin)
{
	GPIOB->ODR &= ~(0x1ul << GPIOB_Pin);  // set 0
}

//------------------------------------
 
void LCD1602_ClearScreen()   // set screen by char 0x20ul
  {
     LCD1602_WriteCmd(0x01);
 }
	//-----------------------------------
void LCD1602_currest()  //cursor back to 0,0
  {
     LCD1602_WriteCmd(0x02ul);
 }
 //------------------------------------
void LCD_entry_mod(u8 ID, u8 SH){
 	u8 cmd = 0x04ul;
 	if(ID==1){ cmd |= 0x1ul << 1;}
 	if(SH==1){ cmd |= 0x1ul ;}
  
 	LCD1602_WriteCmd(cmd); 
 }  
void cusr_ctrl(u8 Dp,u8 csr,u8 blk){
 	u8 cmd = 0x8ul;
 	if(Dp==1){ cmd |= 0x1ul << 2;}     //Dp =1()
 	if(csr==1){ cmd |= 0x1ul << 1;}    //csr =1()
 	if(blk==1){ cmd |= 0x1ul ;}		  // blk =1()
 	LCD1602_WriteCmd(cmd); 
 } 
 
void dp_shift(u8 SC,u8 RL){
    u8 cmd = 0x10ul;         ///0b0001 0000
 	if(SC==1){ cmd |= 0x1ul << 3;}    // sc=1 ()
 	if(RL==1){ cmd |= 0x1ul << 2;}    // RL=1 ()
    LCD1602_WriteCmd(cmd); 
 } 
  	
void func_set(u8 DL,u8 N, u8 F){   //
    u8 cmd = 0x20ul;      //bx0010 0000
    if(DL==1){ cmd |= 0x1ul << 4;}     // DL=1(8-bit), DL=0(4-bit)
 	if(N==1){ cmd |= 0x1ul << 3;}      // N=1(2-line), N=0(1-line)
    if(F==1){ cmd |= 0x1ul << 2;}     // F=1(5x11), F=0(5x8),
  	
    LCD1602_WriteCmd(cmd); 
 }  
 
 void setCGRAM_addr(u8 addr){
  	u8 cmd = 0x40ul + addr;  // DB6 =1
    LCD1602_WriteCmd(cmd); 
 } 
  void setDDRAM_addr(u8 addr){
  	u8 cmd = 0x80ul + addr;    // DB7 =1
    LCD1602_WriteCmd(cmd); 
 } 	
//----------------------------------
u8 LCD_ReadADDR(void)
{
  u8 sta;
    LCD_RS_L();    //=0;
    LCD_RW_H();    //=1;
	GPIOC->MODER &= ~(0xfffful);   //clear MODER
	GPIOC->MODER |= 0xaaaaul;      //set Moder to bx1010 -->input

    LCD_EN_H();   // =1;
    LCD_delay(5);
    sta = (GPIOC ->IDR);
    LCD_EN_L();   // =0;
  return sta;
}

//------------------------------

//--------show line1 line2 --------------------------------------
void LCD1602_show(u8 *line1, u8 *line2){	
	u8 i;
	LCD1602_ClearScreen();
	LCD_entry_mod(1,0);  //change 0 =>revers, 1= whole screen	
	LCD1602_SetCursor( 0, 0);
	for(i=0;i<16;i++){	
		LCD1602_WriteData(line1[i])	;}
	LCD1602_SetCursor( 0, 1);
	for(i=0;i<16;i++){	
		LCD1602_WriteData(line2[i])	;}
	}
	
//******************************************

编写属于 LCD1602 的 header 档
下面来谈谈 header 档的 应用。
以前学的时候都知道 C语言的可携带性/可移植性 很好,是因为有 header 档案,由于每经验所以都是一知半解。
在这里插入图片描述
从上面的图的左边可以看到 我把 main.c 主档 和 LCD1602_cmd.c 放在同一个档案夹。就是在编译的时候是一起操作的。至于如何链接起来执行就要靠这个 include

#include "lcd1602.h"  

同时在 main.c 和 LCD1602_cmd.c 都要有。
以前不了解 h 档 都是把 #include “lcd1602_cmd.c” 当成方法。可以看到在 main.c 里面 我把 #include “lcd1602_cmd.c” 注解掉,依然可以执行。
下边的代码就是我编写的 “lcd1602.h” 档。

#ifndef __LCD1602_H
 #define __LCD1602_H 
 
 /***************************????????????*****************************/
#define u8 unsigned char
#define u16 unsigned short
#define u32 unsigned int 
#define RS 0
#define RW 1
#define EN 2
#define BF 7

 #define LCD_RS_H()    GPIOB_SetBits( RS )   //1602 data
 #define LCD_RS_L()    GPIOB_ResetBits( RS )  //1602 command
 
 #define LCD_RW_H()    GPIOB_SetBits( RW  )  //1602 readdata
 #define LCD_RW_L()    GPIOB_ResetBits( RW  ) //1602 writedata

 #define LCD_EN_H()    GPIOB_SetBits( 2 )   //1602  enable 
 #define LCD_EN_L()    GPIOB_ResetBits( 2 )
 
 #define LCD_clr_dp    LCD_WriteCmd(ox1ul);   
 #define LCD_csr_rt    LCD_WriteCmd(ox2ul);  
 
 #define DATAOUT( x ) GPIO_Write( GPIOA, x ) //1602?8??????
 #define upLine_s     0x00ul
 #define downLine_s  0x40ul

 void GPIO_Write(u8 temp);
 void GPIO_Configuration(void);
 
 void LCD1602_Init(void);
 u8 LCD_CheckBusy(void);
 void LCD1602_Wait_Ready(void);
 
 void LCD1602_WriteCmd( u8 cmd );
 
 void LCD1602_WriteData( u8 data );
  
 void LCD1602_SetCursor( u8 x, u8 line );
 
 void LCD1602_Show_Str( u8 x, u8 y, u8 *str );
 void LCD1602_DisNumber(u8 x,u8 y, u8 Num);
 void LCD1602_DisChar(u8 x, u8 y, u8 ch);
 
 void GPIOB_SetBits(u8 GPIOB_Pin);
 void GPIOB_ResetBits(u8 GPIOB_Pin);

 void LCD1602_ClearScreen(void); 
 void LCD1602_currest(void);
 void LCD_entry_mod(u8 ID, u8 SH);
 void cusr_ctrl(u8 Dp,u8 csr,u8 blk);
 
 void dp_shift(u8 SC,u8 RL);
 void func_set(u8 DL,u8 N, u8 F);

 void setCGRAM_addr(u8 addr);
 void setDDRAM_addr(u8 addr);

 void LCD_delay(u32 x);
 u8 LCD_ReadADDR(void);
 void LCD1602_show(u8 *line1,u8 *line2);
 #endif

下面列的是另一个样本,可以参考一下 h 档的重要结构

time3.h

#ifndef _TIME3_H_
#define _TIME3_H_
	void TIM3_Int_Init(unsigned short psc, unsigned short arr);
#endif

main.c 档

以下main.c 档的内容,我留下许多实验的痕迹,有兴趣的人可以自己修改看看。下一步再加上 USART 的外接传输就可以透过手机传讯息到 F072 的主板了

/**   Project name : LCD 1602 
*   GPIOC 0~7: LCD data b0~b7
*   RS ->PB0, Rw ->PB1, EN ->PB2
--------------------------------------------------------------------------------------*/

#include <stdio.h>

#include "stm32f0xx.h"          // File name depends on device used
#include "RTE_Components.h"      // Component selection 
#include "lcd1602.h"  
//#include "bt2uart.h" 
//#include "lcd1602_cmd.c"  

extern void stdout_init (void);
//extern void GPIO_Configuration(void);

volatile uint32_t msTicks;         // Counter for millisecond Interval

#define NUM_KEYS  1                     /* Number of available keys           */

/* Keys for NUCLEO Board */

extern void  Config_PA910(void); // for Bluetooth    PA.9(Tx)->HC05(Rx),  PA.10(Rx)->HC05(Tx)
extern void  Config_uart1(void); // for BlueTooth
extern void PutCha(u8 ch);
#define USER    1
#define u8 unsigned char
#define u16 unsigned short
#define u32 unsigned int
/*--------------------------------------------------------------------------------*/
// SysTick Interrupt Handler
/*--------------------------------------------------------------------------------*/
void SysTick_Handler (void) 
{       
    msTicks++;           // Increment Counter
}

/*--------------------------------------------------------------------------------*/
// Delay: delay a number of Systicks
/*--------------------------------------------------------------------------------*/
void Delay(uint32_t dlyTicks){
	uint32_t currentTicks;
	
	currentTicks = msTicks;
	while( (msTicks - currentTicks) < dlyTicks ){
		  __NOP();
	}
}

/**-----------------------------------------------------------------------------
  * @brief  Configures the System clock frequency, AHB/APBx prescalers and Flash
  *         settings.
  * @note   This function should be called only once the RCC clock configuration
  *         is reset to the default reset state (done in SystemInit() function).
  * @param  None
  * @retval None
--------------------------------------------------------------------------------  */
static void SetSysClock(void)
{
	SystemCoreClock = 48000000;
  /* SYSCLK, HCLK, PCLK configuration ----------------------------------------*/

  /* At this stage the HSI is already enabled */

  /* Enable Prefetch Buffer and set Flash Latency */
  FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
 
  /* HCLK = SYSCLK */
  RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
  /* PCLK = HCLK */
  RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;

  /* PLL configuration = (HSI/2) * 12 = ~48 MHz */
  RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL));
  RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_DIV2 | RCC_CFGR_PLLMUL12);
            
  /* Enable PLL */
  RCC->CR |= RCC_CR_PLLON;

  /* Wait till PLL is ready */
  while((RCC->CR & RCC_CR_PLLRDY) == 0)
  {
  }

  /* Select PLL as system clock source */
  RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
  RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

  /* Wait till PLL is used as system clock source */
  while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
  {
  }
}
		
/*--------------------------------------------------------------------------------*/
// Button_Init(void)        ;Initialize button
// PC.13 to control User botton, set PC.13 is input pin 
/*--------------------------------------------------------------------------------*/
void Button_Init(void) {

  RCC->AHBENR |=  (1ul << 19);                  // Enable GPIOC clock       
  GPIOC->MODER &= ~(3ul << 2*13);               // Set PC.13 is input  
   
}

/*------------------------------------------------------------------------------*/
//uint32_t Button_GetState(void)
// Get USER button (PC.13) state
// return: 1 means USER key pressed
/*------------------------------------------------------------------------------*/
uint32_t Button_GetState (void) {

  uint32_t val = 0;

  if ((GPIOC->IDR & (1ul << 13)) == 0) {         //When USER button pressed PC.13=0
    val |= USER;                                 // set USER button pressed
  }
  return (val);

}

/*--------------------------------------------------------------------------------*/
// MPU setup process
/*--------------------------------------------------------------------------------*/



/*--------------------------------------------------------------------------------*/
// The processor clock is initialized by CMSIS startup + system file
/*--------------------------------------------------------------------------------*/
int main (void) {        // User application starts here
	
		/* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */
  SetSysClock();
	
  stdout_init();              // Initialize USART 2(PA3 to USART2_RX,PA2 to USART2_TX)  
		                                            
  SysTick_Config(SystemCoreClock/1000);      // System Tick Initializes,set SysTick 1ms interrupt
	
	GPIO_Configuration();
	LCD1602_Init();
    Config_PA910(); // for Bluetooth    PA.9(Tx)->HC05(Rx),  PA.10(Rx)->HC05(Tx)
    Config_uart1(); // for BlueTooth

//------------------------------------------

    unsigned char str[]="Hello world!";
    unsigned  char *w=str;	
    u8  word;
	u8 x, y, i;
	x= 0 ;
//while(1)	{
	LCD1602_ClearScreen();
	//----------print Hello------------------------------

	 LCD1602_SetCursor( 0, 0 );
	 LCD1602_Show_Str( 2, 0, w );
	 Delay(1000);
	 LCD1602_ClearScreen();
//------------print A--------------------------

//-----------auto chang line-------------------------------
		  word=0x41ul;

		for(i=0; i<32;i++){
			y = i/16;
			x = i-16;
			if (y==0){ LCD1602_SetCursor( i, y);}
			if (y==1){ LCD1602_SetCursor( x, y);}
			LCD1602_WriteData(word+i);
			Delay(50);
		}
		

//-----------Read Address-------------------------------		
	u8 Hex[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
	u8 line1[] ={'a','d','d','r',':',0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul} ;
	u8 line2[] ={0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul,0x20ul} ;
    u8 *lineu=line1;	
	u8 *lined=line2;	
		
		
    u8 addr= LCD_ReadADDR();
		line1[7] = Hex[(addr >> 4) & 0xful];
		line1[8] = Hex[(addr) & 0xful];
//--------show line1 line2 --------------------------------------
	   LCD1602_show( lineu, lined);
		
//-----------------------------------------------------
	LCD1602_SetCursor( 0, 1 );
//		int h=0;
	for (i=5; i<25 ;i++) {
		 //PutCha(i);
		LCD1602_WriteData(word+i);
		if (USART1->ISR &( 0x1ul <<7)) {
			USART1->TDR =word+i;
			Delay(100);	
		}
	}
//-----------------------------------------------------		
	LCD1602_SetCursor( 0, 1 );
	u8 pos =0;
	u8 buffer=0;
    uint8_t data[20]; 
		 
	USART1->CR1 = USART_CR1_RXNEIE | USART_CR1_RE | USART_CR1_UE;
		 
while(1){		
  
	for (buffer=0;buffer<20; buffer++)
	{
	while ((USART1->ISR & USART_ISR_RXNE) == USART_ISR_RXNE) 
		{
    	data[buffer] = (uint8_t) USART1->RDR;    //receive data 
		}
	}
	/*	for(i=0; i<=buffer;i++){	LCD1602_WriteData(data[i]); pos++;}
		
		buffer++;

		if ((data ==0x0d) || (data ==0x0a)) {;}
			else {

	 	LCD1602_WriteData(Hex[(data  >> 4) & 0xful]);
	
 		LCD1602_WriteData( Hex[(data) & 0xful]);
					
	 	pos +=2;*/
	 	
		if (pos>16){
			pos=0; 	
			LCD1602_SetCursor( 0, 1 );}
	

	}
	

		//------------------------------------------------
	
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值