在Keil5软件利用矩阵按键和LCD1602实现计算器功能,要使用LCD1602代码(加减除、十进制和二进制转换) 注:除法运算结果显示保留两位小数
时间: 2024-02-09 22:10:38 浏览: 104
好的,下面我将给出更详细的步骤,帮助你实现在Keil5软件利用矩阵按键和LCD1602实现计算器功能,并使用LCD1602代码(加减除、十进制和二进制转换),并且除法运算结果显示保留两位小数。
步骤1:矩阵按键驱动程序
首先,我们需要编写矩阵按键的驱动程序。在Keil5中,我们可以使用GPIO来控制矩阵按键。
在程序中,我们需要定义每个按键的行和列引脚,然后轮询行和列,以检测按键是否被按下。一旦检测到按键被按下,我们可以返回它所对应的按键编码。
以下是一个简单的矩阵按键驱动程序示例:
```
#include "stm32f10x.h"
#define ROWS 4
#define COLS 4
#define ROW1_GPIO GPIOB
#define ROW1_PIN GPIO_Pin_0
#define ROW2_GPIO GPIOB
#define ROW2_PIN GPIO_Pin_1
#define ROW3_GPIO GPIOB
#define ROW3_PIN GPIO_Pin_2
#define ROW4_GPIO GPIOB
#define ROW4_PIN GPIO_Pin_3
#define COL1_GPIO GPIOB
#define COL1_PIN GPIO_Pin_4
#define COL2_GPIO GPIOB
#define COL2_PIN GPIO_Pin_5
#define COL3_GPIO GPIOB
#define COL3_PIN GPIO_Pin_6
#define COL4_GPIO GPIOB
#define COL4_PIN GPIO_Pin_7
const uint8_t keys[ROWS][COLS] = {
{1, 2, 3, 0xA},
{4, 5, 6, 0xB},
{7, 8, 9, 0xC},
{0, 0xF, 0xE, 0xD}
};
void keypad_init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = ROW1_PIN | ROW2_PIN | ROW3_PIN | ROW4_PIN;
GPIO_Init(ROW1_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Pin = COL1_PIN | COL2_PIN | COL3_PIN | COL4_PIN;
GPIO_Init(COL1_GPIO, &GPIO_InitStructure);
}
uint8_t keypad_scan(void) {
uint8_t row, col;
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
for (row = 0; row < ROWS; row++) {
GPIO_InitStructure.GPIO_Pin = (1 << row);
GPIO_Init(ROW1_GPIO, &GPIO_InitStructure);
for (col = 0; col < COLS; col++) {
if (GPIO_ReadInputDataBit(COL1_GPIO, (1 << col))) {
while (GPIO_ReadInputDataBit(COL1_GPIO, (1 << col))) {}
return keys[row][col];
}
}
GPIO_InitStructure.GPIO_Pin = 0;
GPIO_Init(ROW1_GPIO, &GPIO_InitStructure);
}
return 0xFF;
}
```
步骤2:计算器程序
接下来,我们需要编写计算器程序。在程序中,我们需要定义缓冲区来存储按键输入,并在需要时将其转换为数字和运算符。
我们可以使用switch语句来检测按键输入,并执行相应的操作。例如,如果按下了数字键,则将其添加到缓冲区的末尾。如果按下了运算符键,则将缓冲区中的内容解析为数字,并执行相应的操作,例如加法、减法、乘法或除法。在除法运算中,我们需要将结果乘以100,以保留两位小数。
最后,我们需要将计算结果显示在LCD上。
以下是一个简单的计算器程序示例:
```
#include "stm32f10x.h"
#include "lcd1602.h"
#define BUFFER_SIZE 16
char buffer[BUFFER_SIZE];
int buffer_position = 0;
void calculator_init(void) {
buffer[0] = '\0';
buffer_position = 0;
}
void calculator_append(char c) {
if (buffer_position < BUFFER_SIZE - 1) {
buffer[buffer_position++] = c;
buffer[buffer_position] = '\0';
}
}
void calculator_clear(void) {
buffer[0] = '\0';
buffer_position = 0;
}
void calculator_evaluate(void) {
char operator = '\0';
int operand1 = 0;
int operand2 = 0;
float result = 0;
for (int i = 0; i < buffer_position; i++) {
char c = buffer[i];
if (c >= '0' && c <= '9') {
if (operator == '\0') {
operand1 = operand1 * 10 + (c - '0');
} else {
operand2 = operand2 * 10 + (c - '0');
}
} else if (c == '+') {
operator = '+';
} else if (c == '-') {
operator = '-';
} else if (c == '*') {
operator = '*';
} else if (c == '/') {
operator = '/';
}
}
switch (operator) {
case '+':
result = operand1 + operand2;
break;
case '-':
result = operand1 - operand2;
break;
case '*':
result = operand1 * operand2;
break;
case '/':
result = ((float)operand1 / (float)operand2) * 100;
break;
}
lcd1602_clear();
lcd1602_puts("Result: ");
lcd1602_put_float(result, 2);
}
void calculator_handle_key(uint8_t key) {
switch (key) {
case 0:
calculator_append('0');
break;
case 1:
calculator_append('1');
break;
case 2:
calculator_append('2');
break;
case 3:
calculator_append('+');
break;
case 4:
calculator_append('3');
break;
case 5:
calculator_append('4');
break;
case 6:
calculator_append('5');
break;
case 7:
calculator_append('-');
break;
case 8:
calculator_append('6');
break;
case 9:
calculator_append('7');
break;
case 10:
calculator_append('8');
break;
case 11:
calculator_append('*');
break;
case 12:
calculator_append('9');
break;
case 13:
calculator_append('.');
break;
case 14:
calculator_evaluate();
break;
case 15:
calculator_clear();
break;
}
lcd1602_clear();
lcd1602_puts(buffer);
}
void calculator_run(void) {
uint8_t key;
lcd1602_init();
calculator_init();
while (1) {
key = keypad_scan();
if (key != 0xFF) {
calculator_handle_key(key);
}
}
}
```
步骤3:LCD1602驱动程序
最后,我们需要编写LCD1602的驱动程序,以便在LCD上显示计算结果。在程序中,我们需要定义LCD的数据线和控制线,并在需要时向LCD发送命令和数据。
以下是一个简单的LCD1602驱动程序示例:
```
#include "stm32f10x.h"
#define LCD_RS_GPIO GPIOB
#define LCD_RS_PIN GPIO_Pin_8
#define LCD_E_GPIO GPIOB
#define LCD_E_PIN GPIO_Pin_9
#define LCD_D4_GPIO GPIOB
#define LCD_D4_PIN GPIO_Pin_10
#define LCD_D5_GPIO GPIOB
#define LCD_D5_PIN GPIO_Pin_11
#define LCD_D6_GPIO GPIOB
#define LCD_D6_PIN GPIO_Pin_12
#define LCD_D7_GPIO GPIOB
#define LCD_D7_PIN GPIO_Pin_13
void lcd1602_init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = LCD_RS_PIN | LCD_E_PIN | LCD_D4_PIN | LCD_D5_PIN | LCD_D6_PIN | LCD_D7_PIN;
GPIO_Init(LCD_RS_GPIO, &GPIO_InitStructure);
lcd1602_send_command(0x33);
lcd1602_send_command(0x32);
lcd1602_send_command(0x28);
lcd1602_send_command(0x0C);
lcd1602_send_command(0x06);
lcd1602_send_command(0x01);
}
void lcd1602_send_nibble(uint8_t nibble) {
GPIO_WriteBit(LCD_D4_GPIO, LCD_D4_PIN, (nibble & 0x01) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_D5_GPIO, LCD_D5_PIN, (nibble & 0x02) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_D6_GPIO, LCD_D6_PIN, (nibble & 0x04) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(LCD_D7_GPIO, LCD_D7_PIN, (nibble & 0x08) ? Bit_SET : Bit_RESET);
}
void lcd1602_send_command(uint8_t command) {
GPIO_WriteBit(LCD_RS_GPIO, LCD_RS_PIN, Bit_RESET);
lcd1602_send_nibble(command >> 4);
GPIO_WriteBit(LCD_E_GPIO, LCD_E_PIN, Bit_SET);
GPIO_WriteBit(LCD_E_GPIO, LCD_E_PIN, Bit_RESET);
lcd1602_send_nibble(command & 0x0F);
GPIO_WriteBit(LCD_E_GPIO, LCD_E_PIN, Bit_SET);
GPIO_WriteBit(LCD_E_GPIO, LCD_E_PIN, Bit_RESET);
}
void lcd1602_send_data(uint8_t data) {
GPIO_WriteBit(LCD_RS_GPIO, LCD_RS_PIN, Bit_SET);
lcd1602_send_nibble(data >> 4);
GPIO_WriteBit(LCD_E_GPIO, LCD_E_PIN, Bit_SET);
GPIO_WriteBit(LCD_E_GPIO, LCD_E_PIN, Bit_RESET);
lcd1602_send_nibble(data & 0x0F);
GPIO_WriteBit(LCD_E_GPIO, LCD_E_PIN, Bit_SET);
GPIO_WriteBit(LCD_E_GPIO, LCD_E_PIN, Bit_RESET);
}
void lcd1602_clear(void) {
lcd1602_send_command(0x01);
}
void lcd1602_puts(char *str) {
while (*str) {
lcd1602_send_data(*str++);
}
}
void lcd1602_put_float(float number, int precision) {
char buffer[16];
int integer = (int)number;
int decimal = (int)((number - integer) * 100);
if (decimal < 0) {
decimal = -decimal;
}
sprintf(buffer, "%d.%0*d", integer, precision, decimal);
lcd1602_puts(buffer);
}
```
希望这些信息对你有所帮助!
阅读全文