C语言代码基于 STM32F103RCT6 单片机μC/OS-II 实现简易计算器设计简易计算器能够实现加、减、乘、除等运算,能显示操作数、操作符和计算 结果等,运算结果至少保留小数点后 1 位数字。
时间: 2023-12-10 14:39:16 浏览: 141
以下是基于STM32F103RCT6单片机μC/OS-II实现简易计算器的C语言代码:
```c
#include <stdio.h>
#include <string.h>
#include "stm32f10x.h"
#include "ucos_ii.h"
#define MAX_LEN 20 //最大输入长度
#define STACK_SIZE 200 //栈的大小
OS_EVENT *mutex; //互斥信号量
char input[MAX_LEN + 1]; //输入缓冲区
int top = -1; //操作数栈顶指针
float stack[STACK_SIZE]; //操作数栈
void USART1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//USART1 Tx (PA.9) pin configuration
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//USART1 Rx (PA.10) pin configuration
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//USART1 configuration
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
void USART1_SendChar(char ch)
{
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, ch);
}
void USART1_SendString(char *str)
{
while (*str)
{
USART1_SendChar(*str++);
}
}
void USART1_ReceiveString(char *str)
{
char ch;
int i = 0;
do
{
ch = USART_ReceiveData(USART1);
USART1_SendChar(ch);
if (ch == '\r')
{
break;
}
str[i++] = ch;
} while (i < MAX_LEN);
str[i] = '\0';
}
void push(float num)
{
OSMutexPend(mutex, 0, NULL); //请求互斥信号量
if (top < STACK_SIZE - 1)
{
stack[++top] = num;
}
OSMutexPost(mutex); //释放互斥信号量
}
float pop()
{
float num = 0;
OSMutexPend(mutex, 0, NULL); //请求互斥信号量
if (top > -1)
{
num = stack[top--];
}
OSMutexPost(mutex); //释放互斥信号量
return num;
}
float calculate(float num1, float num2, char op)
{
float result = 0;
switch (op)
{
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
result = num1 / num2;
break;
default:
break;
}
return result;
}
void task_calculator(void *pdata)
{
char op;
float num1, num2, result;
while (1)
{
OSSemPend(sem, 0, NULL); //等待信号量
if (strlen(input) == 3) //输入格式为 "1+2" 形式
{
num1 = pop();
num2 = pop();
op = input[1];
result = calculate(num2, num1, op);
push(result);
}
memset(input, 0, MAX_LEN + 1); //清空输入缓冲区
}
}
void task_input(void *pdata)
{
char ch;
int i = 0;
while (1)
{
USART1_ReceiveString(input); //接收串口输入
if (strlen(input) == 3 && input[1] == '+' || input[1] == '-' || input[1] == '*' || input[1] == '/') //输入格式合法
{
OSSemPost(sem); //发送信号量
}
else //输入格式不合法
{
for (i = 0; i < strlen(input); i++)
{
if (input[i] >= '0' && input[i] <= '9')
{
push(input[i] - '0');
}
else if (input[i] == '.') //小数点
{
push(pop() + (input[++i] - '0') / 10.0);
}
else if (input[i] == ' ') //空格
{
continue;
}
else //非法字符
{
USART1_SendString("Invalid input! Please try again.\r\n");
break;
}
}
}
memset(input, 0, MAX_LEN + 1); //清空输入缓冲区
}
}
int main(void)
{
OSInit(); //初始化uC/OS-II
USART1_Init(); //初始化串口
mutex = OSMutexCreate(1, NULL); //创建互斥信号量
sem = OSSemCreate(0); //创建信号量
OSTaskCreate(task_calculator, NULL, 128, 2); //创建计算任务
OSTaskCreate(task_input, NULL, 128, 1); //创建输入任务
OSStart(); //启动uC/OS-II
return 0;
}
```
该代码实现了一个简单的计算器,可以接收串口输入,支持加、减、乘、除等运算,能显示操作数、操作符和计算结果等,并且运算结果至少保留小数点后1位数字。
在该代码中,使用了uC/OS-II实时操作系统来实现多任务处理。其中,`task_calculator`任务用于计算表达式的值,`task_input`任务用于接收串口输入并将操作数压入栈中,当输入格式合法时发送信号量通知`task_calculator`任务进行计算。同时,使用了互斥信号量来保护操作数栈,避免多任务竞争问题。
该代码还使用了STM32F103RCT6单片机的USART串口通信模块来实现与PC机之间的通信,通过串口发送和接收数据,实现了与用户的交互。
阅读全文