STM32F072RB 模拟板,本身没有显示器,如果能加装一个,那么在实验的时候可以监看程式进行状态就方便许多了。于是我就用手边的 LCD 1602,做一个试试!以下就是整个过程。
LCD1602 规格資料LCD1602 是一个非常普遍的材料,规格同一,书面資料也是相互抄袭,从网络上很轻易的就能找到,我这里附上的是英文的資料,中文資料可以自己再去找找。
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; iMODER &= ~(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 != ' ')
{
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 <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]) ;}
}
/
#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); #endifmain.c 档
以下main.c 档的内容,我留下许多实验的痕迹,有兴趣的人可以自己修改看看。下一步再加上 USART 的外接传输就可以透过手机传讯息到 F072 的主板了
#include#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 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(); } } static void SetSysClock(void) { SystemCoreClock = 48000000; FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY; RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1; RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL)); RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_DIV2 | RCC_CFGR_PLLMUL12); RCC->CR |= RCC_CR_PLLON; while((RCC->CR & RCC_CR_PLLRDY) == 0) { } RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; 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 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 } } if (pos>16){ pos=0; LCD1602_SetCursor( 0, 1 );} } //------------------------------------------------ }



