1. 項(xiàng)目介紹
計(jì)算器是最常見的工具了,現(xiàn)在不管是手機(jī)、電腦都帶有計(jì)算器功能,支持強(qiáng)大的科學(xué)運(yùn)算等。
當(dāng)前文章介紹的是STM32+LCD觸摸屏設(shè)計(jì)的一個(gè)觸摸計(jì)算器功能,實(shí)現(xiàn)基本的加減乘除,二進(jìn)制轉(zhuǎn)換顯示等功能。LCD屏使用的是3.5寸帶觸摸屏的顯示屏,方便操作屏幕,MCU采用STM32F103ZET6。
設(shè)計(jì)的這個(gè)計(jì)算器用到的硬件不多,主要是LCD屏和觸摸屏,用到了一個(gè)W25Q64存儲(chǔ)芯片,保存觸摸屏校準(zhǔn)后的一些配置數(shù)據(jù),這個(gè)可有可無,只是方便不需要每次斷電后重新校準(zhǔn)。
運(yùn)行效果圖如下:
完整項(xiàng)目源碼下載地址: https://download.csdn.net/download/xiaolong1126626497/63976226
視頻演示地址: https://live.csdn.net/v/182604
2. 項(xiàng)目實(shí)現(xiàn)
2.1 運(yùn)算實(shí)現(xiàn)思路
功能介紹:
在除法計(jì)算過程中,如果商是小數(shù),計(jì)算器得到的結(jié)果也是精準(zhǔn)的,是double類型。 在計(jì)算過程中,可以實(shí)現(xiàn)連續(xù)運(yùn)算。過程中是逐步計(jì)算出數(shù)據(jù)來的。
觸摸校準(zhǔn)流程:
計(jì)算器算法:
LCD的驅(qū)動(dòng)芯片是NT35310,支持8080時(shí)序讀寫寄存器,當(dāng)前項(xiàng)目采用模擬時(shí)序控制LCD屏,移植性較高。
核心代碼如下:
#include "lcd.h"
#include "stdlib.h"
#include "usart.h"
#include "delay.h"
#include "math.h"
#include "timer.h"
#include "spi.h"
#include "usart.h"
#include
#include "key.h"
#include "rtc.h"
#include "wannianli.h"
#include "touch.h"
#include "led.h"
#include
#include "shuzimo.h"
#include
#include "calculator.h"
/*
函數(shù)功能:寫LCD數(shù)據(jù)
函數(shù)參數(shù):data:要寫入的值
*/
void LcdWriteData(u16 data)
{
LCD_RS=1; //寫數(shù)據(jù)
LCD_CS=0; //選中LCD屏
//輸出數(shù)據(jù)
LCD_DATA0=(data>>0&0x01);
LCD_DATA1=(data>>1&0x01);
LCD_DATA2=(data>>2&0x01);
LCD_DATA3=(data>>3&0x01);
LCD_DATA4=(data>>4&0x01);
LCD_DATA5=(data>>5&0x01);
LCD_DATA6=(data>>6&0x01);
LCD_DATA7=(data>>7&0x01);
LCD_DATA8=(data>>8&0x01);
LCD_DATA9=(data>>9&0x01);
LCD_DATA10=(data>>10&0x01);
LCD_DATA11=(data>>11&0x01);
LCD_DATA12=(data>>12&0x01);
LCD_DATA13=(data>>13&0x01);
LCD_DATA14=(data>>14&0x01);
LCD_DATA15=(data>>15&0x01);
LCD_WR=0; //表示準(zhǔn)備寫數(shù)據(jù)
LCD_WR=1; //表示數(shù)據(jù)寫完成
LCD_CS=1; //取消LCD屏片選
}
/*
函數(shù)功能:寫寄存器
參 數(shù):regval:寄存器值
*/
void LcdWriteReg(u16 data)
{
LCD_RS=0; //寫命令
LCD_CS=0; //選中LCD屏
//輸出數(shù)據(jù)
LCD_DATA0=(data>>0&0x01);
LCD_DATA1=(data>>1&0x01);
LCD_DATA2=(data>>2&0x01);
LCD_DATA3=(data>>3&0x01);
LCD_DATA4=(data>>4&0x01);
LCD_DATA5=(data>>5&0x01);
LCD_DATA6=(data>>6&0x01);
LCD_DATA7=(data>>7&0x01);
LCD_DATA8=(data>>8&0x01);
LCD_DATA9=(data>>9&0x01);
LCD_DATA10=(data>>10&0x01);
LCD_DATA11=(data>>11&0x01);
LCD_DATA12=(data>>12&0x01);
LCD_DATA13=(data>>13&0x01);
LCD_DATA14=(data>>14&0x01);
LCD_DATA15=(data>>15&0x01);
LCD_WR=0; //表示準(zhǔn)備寫數(shù)據(jù)
LCD_WR=1; //表示數(shù)據(jù)寫完成
LCD_CS=1; //取消LCD屏片選
}
/*
函數(shù)功能:設(shè)置光標(biāo)位置
函數(shù)參數(shù):
Xpos:橫坐標(biāo)
Ypos:縱坐標(biāo)
*/
void LcdSetCursor(u16 Xpos, u16 Ypos)
{
LcdWriteReg(0X2A);
LcdWriteData(Xpos>>8);
LcdWriteData(Xpos&0XFF);
LcdWriteReg(0X2B);
LcdWriteData(Ypos>>8);
LcdWriteData(Ypos&0XFF);
}
/*
功 能: 初始化LCD屏幕
說 明: 用于3.5寸屏幕的初始化。
LCD ID:5310
硬件連接:
硬件連接:
FSMC_D0 ------PD14
FSMC_D1 ------PD15
FSMC_D2 ------PD0
FSMC_D3 ------PD1
FSMC_D4 ------PE7
FSMC_D5 ------PE8
FSMC_D6 ------PE9
FSMC_D7 ------PE10
FSMC_D8 ------PE11
FSMC_D9 ------PE12
FSMC_D10 -----PE13
FSMC_D11 ------PE14
FSMC_D12 ------PE15
FSMC_D13 ------PD8
FSMC_D14 ------PD9
FSMC_D15 ------PD10
LCD_BL(背光) ----PB0
FSMC_NE4(CS) --->PG12
FSMC_NWE(WR/CLK)--->PD5
FSMC_NOE(RD) --->PD4
FSMC_A10(RS) --->PG0
*/
void LcdInit(void)
{
RCC->APB2ENR|=1<<3; //使能PORTB時(shí)鐘
RCC->APB2ENR|=1<<5; //使能PORTD時(shí)鐘
RCC->APB2ENR|=1<<6; //使能PORTE時(shí)鐘
RCC->APB2ENR|=1<<8; //使能PORTG時(shí)鐘
/*1. 初始化控制IO口*/
GPIOB->CRL&=0xFFFFFFF0; //LCD_BL(背光)
GPIOB->CRL|=0x0000000B;
GPIOG->CRH&=0xFFF0FFFF; //FSMC_NE4(CS)
GPIOG->CRH|=0x00030000;
GPIOD->CRL&=0xFF00FFFF; //FSMC_NWE(WR/CLK)\FSMC_NOE(RD)
GPIOD->CRL|=0x00330000;
GPIOG->CRL&=0xFFFFFFF0; //FSMC_A10(RS)
GPIOG->CRL|=0x00000003;
/*2. 初始化數(shù)據(jù)線*/
GPIOD->CRL&=0xFFFFFF00;
GPIOD->CRL|=0x00000033;
GPIOD->CRH&=0x00FFF000;
GPIOD->CRH|=0x33000333;
GPIOE->CRL&=0x0FFFFFFF;
GPIOE->CRL|=0x30000000;
GPIOE->CRH&=0x00000000;
GPIOE->CRH|=0x33333333;
}
/*
函數(shù)功能:畫點(diǎn)
函數(shù)形參:x,y:坐標(biāo)
*/
void LcdDrawPoint(u16 x,u16 y,u16 color)
{
LcdSetCursor(x,y); //設(shè)置光標(biāo)位置
LcdWriteReg(0X2C); //開始寫入GRAM
LcdWriteData(color);
}
/*
函數(shù)功能:顯示一個(gè)漢字
*/
void LcdShowFont(u8 *font,u16 x,u16 y,u16 size,u16 high,u16 color1,u16 color2)
{
u8 data;
u16 i,j,k;
for(i=0;i;i++)>
2.3 觸摸屏代碼
觸摸屏采用XPT2046芯片,一個(gè)24位的ADC芯片,支持SPI接口。
代碼里主要完成兩個(gè)操作: 1. 讀取XPT2046檢測(cè)到的數(shù)據(jù) 2. 實(shí)現(xiàn)觸摸屏校準(zhǔn)算法
代碼如下:
#include "touch.h"
#include "delay.h"
#include "lcd.h"
#include "spi.h"
#include
#define T_MOSI1 GPIOF->ODR|=1<<9;
#define T_MOSI0 GPIOF->ODR&=~(1<<9);
#define T_SCK1 GPIOB->ODR|=1<<1;
#define T_SCK0 GPIOB->ODR&=~(1<<1);
#define T_CS1 GPIOF->ODR|=1<<11;
#define T_CS0 GPIOF->ODR&=~(1<<11);
extern struct kxy
{
float kx;
float ky;
u16 x1;
u16 y1;
u16 x2;
u16 y2;
u16 x3;
u16 y3;
u16 x4;
u16 y4;
u16 xx;
u16 yy;
}xielv;
void touch_lint(void)
{
RCC->APB2ENR|=1<<3; //打開PB口時(shí)鐘
RCC->APB2ENR|=1<<7; //打開PF口時(shí)鐘
GPIOB->CRL&=0XFFFFF00F; //配置PB口
GPIOB->CRL|=0X00000830;
GPIOF->CRH&=0XFFFF000F; //配置PF口
GPIOF->CRH|=0X00003830;
T_SCK1
GPIOF->IDR|=1<<10;
T_CS1;
}
void touch_write(u8 data) //往XPT2046中寫入命令
{
u8 i;
T_CS0
T_SCK0
T_MOSI0
for(i=0;i<8;i++)
{
if(data&0x80) T_MOSI1
else T_MOSI0
T_SCK0
T_SCK1
data=data<<1;
}
}
u16 touch_read(u8 data) //從XPT2046中讀取數(shù)據(jù)
{
u16 i,dat=0;
touch_write(data);
delay_us(6);
for(i=0;i<16;i++)
{
dat=dat<<1;
T_SCK0
T_SCK1
if(GPIOB->IDR&1<<2)
{
dat|=1<<0;
}
}
T_CS1
dat=dat>>4;
return dat;
}
void si_shizi(u16 color)
{
Draw_line(0,10,20,10,color);
Draw_line(10,0,10,20,color);
Draw_line(300,10,320,10,color);
Draw_line(310,0,310,20,color);
Draw_line(0,470,20,470,color);
Draw_line(10,460,10,480,color);
Draw_line(300,470,320,470,color);
Draw_line(310,460,310,480,color);
}
void jiaozhun(u16 x1,u16 y1,u16 x2,u16 y2,u16 x3,u16 y3,u16 x4,u16 y4)
{
xielv.kx=(300.0/(x1-x2)+300.0/(x3-x4))/2;
xielv.ky=(460.0/(y1-y3)+460.0/(y2-y4))/2;
}
void lcd_jiaozhun(void)
{
read_data((u8*)&xielv,791920,sizeof(struct kxy));
if(xielv.kx<0)
{
u8 *buff=malloc(100);
u8 *bufi=malloc(50);
u8 i=0;
u16 x0,y0;
lcd_clear(0,0,YELLOW);
si_shizi(BLUE);
lcd_string((u8*)"校準(zhǔn)開始",buff,16,130,220,767600,32,64);
delay_ms(3000);
juxing_tianchong(80,220,160,16,YELLOW);
lcd_string((u8*)"請(qǐng)點(diǎn)擊第一個(gè)十字中心",bufi,16,80,220,767600,32,64);
while(1)
{
if(!(GPIOF->IDR&1<<10))
{
delay_ms(20);
if(!(GPIOF->IDR&1<<10))
{
x0=touch_read(0xD0);
y0=touch_read(0X90);
i++;
if(i==1)
{
Draw_line(0,10,20,10,YELLOW);
Draw_line(10,0,10,20,YELLOW);
juxing_tianchong(80,220,160,16,YELLOW);
lcd_string((u8*)"請(qǐng)點(diǎn)擊第二個(gè)十字中心",bufi,16,80,220,767600,32,64);
xielv.x1=x0;
xielv.y1=y0;
}
if(i==2)
{
Draw_line(300,10,320,10,YELLOW);
Draw_line(310,0,310,20,YELLOW);
juxing_tianchong(80,220,160,16,YELLOW);
lcd_string((u8*)"請(qǐng)點(diǎn)擊第三個(gè)十字中心",bufi,16,80,220,767600,32,64);
xielv.x2=x0;
xielv.y2=y0;
}
if(i==3)
{
Draw_line(0,470,20,470,YELLOW);
Draw_line(10,460,10,480,YELLOW);
juxing_tianchong(80,220,160,16,YELLOW);
lcd_string((u8*)"請(qǐng)點(diǎn)擊第四個(gè)十字中心",bufi,16,80,220,767600,32,64);
xielv.x3=x0;
xielv.y3=y0;
}
if(i==4)
{
Draw_line(300,470,320,470,YELLOW);
Draw_line(310,460,310,480,YELLOW);
juxing_tianchong(80,220,160,16,YELLOW);
lcd_string((u8*)"校準(zhǔn)完畢",buff,16,130,220,767600,32,64);
delay_ms(3000);
juxing_tianchong(80,220,160,16,YELLOW);
xielv.x4=x0;
xielv.y4=y0;
jiaozhun(xielv.x1,xielv.y1,xielv.x2,xielv.y2,xielv.x3,xielv.y3,xielv.x4,xielv.y4);
break;
}
delay_ms(40);
}
}
}
clear_shanqu(761920);
write_every((u8*)&xielv,sizeof(struct kxy),791920);
}
}
審核編輯:湯梓紅
-
mcu
+關(guān)注
關(guān)注
146文章
17194瀏覽量
351864 -
STM32
+關(guān)注
關(guān)注
2270文章
10914瀏覽量
356712 -
計(jì)算器
+關(guān)注
關(guān)注
16文章
437瀏覽量
37401
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論