基于STM32设计的简易手机

一、项目介绍

基于STM32设计的简易手机可以作为智能手表的模型进行开发,方便老人和儿童佩戴。项目主要是为了解决老年人或儿童使用智能手表时可能遇到的困难,例如操作困难、功能复杂等问题。

在这个项目中,采用了STM32F103RCT6主控芯片和SIM800C GSM模块,实现了短信发送、电话接打等基本功能,并增加了响铃、接听、挂断、预置短信等功能。当检测到新的电话来时,会通过蜂鸣器通知用户,并通过按键进行接电话和挂电话,使操作更加简单易懂。手机还提供4个按键,可以向预先指定的联系人发送4条预置短信,更方便快捷。

image-20230617103157135

image-20230617103208773

img

image-20230607220310330

二、设计思路

2.1 设计目的

实现基于STM32F103RCT6主控芯片的简易手机系统,包括短信发送、电话接打、蜂鸣器通知、按键控制等功能。

2.2 系统硬件设计

系统主要由STM32F103RCT6主控芯片、SIM800C GSM模块、蜂鸣器、LCD显示屏、按键等组成。

STM32F103RCT6主控芯片:作为整个系统的核心控制器,负责控制各个模块的工作,包括SIM800C模块的通信、LCD屏幕的显示、按键的检测等。

SIM800C GSM模块:作为系统与外部通信的核心模块,负责实现短信发送、电话接打等功能。

蜂鸣器:当检测到新的电话来时,通过蜂鸣器通知用户。

LCD显示屏:用于显示系统状态、短信内容、电话号码等信息。

按键:包括接听键、挂断键、短信发送键等,用于实现系统的各种功能。

2.3 系统软件设计

本系统的软件设计主要包括以下几个方面:

(1)SIM800C模块驱动程序的编写,实现短信发送、电话接打等功能。

(2)LCD显示程序的编写,实现信息的显示和操作界面的设计。

(3)按键程序的编写,实现按键的检测和功能的实现。

(4)系统状态机的设计,实现系统状态的切换和各个状态之间的转换。

2.4 系统实现

【1】硬件实现

根据设计方案,完成了硬件电路的设计和制作。其中,STM32F103RCT6主控芯片与SIM800C模块通过串口进行通信,LCD显示屏通过SPI接口进行通信。

【2】软件实现

(1)SIM800C模块驱动程序的编写

根据SIM800C模块的AT指令集,编写了相应的驱动程序,实现了短信发送、电话接打等功能。

  • 初始化SIM800C模块,设置串口通信参数。
  • 发送AT指令,检测SIM800C模块是否正常工作。
  • 实现短信发送功能,包括设置短信内容、发送短信等操作。
  • 实现电话接打功能,包括拨号、接听、挂断等操作。

(2)LCD显示程序的编写

根据LCD显示屏的驱动芯片ST7735S的规格书,编写了相应的LCD显示程序,实现了信息的显示和操作界面的设计。

  • 初始化LCD显示屏,设置SPI通信参数。
  • 实现信息的显示功能,包括电话号码、短信内容等信息的显示。
  • 实现操作界面的设计,包括菜单、按键状态等信息的显示。

(3)按键程序的编写

根据硬件设计中按键的接线方式,编写了相应的按键程序,实现了按键的检测和功能的实现。具体实现过程如下:

  • 初始化按键,设置按键的引脚方向和上下拉电阻。
  • 实现按键的检测功能,包括按键的按下和松开的检测。
  • 实现按键功能的实现,包括接听、挂断、短信发送等功能。

(4)系统状态机的设计

根据系统的功能和状态,设计了相应的状态机,实现系统状态的切换和各个状态之间的转换。具体实现过程如下:

  • 设计系统的状态,包括待机状态、拨号状态、通话状态、短信发送状态等。
  • 实现状态之间的转换,包括按键触发、SIM800C模块的响应等。
  • 实现状态机的循环,不断检测系统状态并执行相应的操作。

三、代码实现

下面是基于STM32F103RCT6设计简易手机的完整代码实现:

#include "stm32f10x.h"
#include "stdio.h"
#include "string.h"

#define SIM800C_BAUDRATE 9600 // SIM800C模块波特率
#define PHONE_NUMBER "123456789" // 需要拨打的电话号码

uint8_t gsm_buffer[100]; // 存储GSM模块返回的数据
uint8_t phone_number[15]; // 存储当前来电的电话号码
volatile uint8_t is_calling = 0; // 是否正在通话中的标志位
volatile uint8_t call_answered = 0; // 是否接听了电话的标志位

void init_usart1(uint32_t baudrate)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);

    GPIO_InitTypeDef gpio_init_struct;
    gpio_init_struct.GPIO_Pin = GPIO_Pin_9;
    gpio_init_struct.GPIO_Mode = GPIO_Mode_AF_PP;
    gpio_init_struct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &gpio_init_struct);

    gpio_init_struct.GPIO_Pin = GPIO_Pin_10;
    gpio_init_struct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &gpio_init_struct);

    USART_InitTypeDef usart_init_struct;
    usart_init_struct.USART_BaudRate = baudrate;
    usart_init_struct.USART_WordLength = USART_WordLength_8b;
    usart_init_struct.USART_StopBits = USART_StopBits_1;
    usart_init_struct.USART_Parity = USART_Parity_No;
    usart_init_struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    usart_init_struct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &usart_init_struct);
    USART_Cmd(USART1, ENABLE);
}

void send_usart1_data(uint8_t *data, uint16_t size)
{
    for (int i = 0; i < size; i++)
    {
        USART_SendData(USART1, data[i]);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
        {
        }
    }
}

uint8_t receive_usart1_data(void)
{
    while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)
    {
    }
    return USART_ReceiveData(USART1);
}

void clear_usart1_buffer(void)
{
    memset(gsm_buffer, 0, sizeof(gsm_buffer));
}

void init_sim800c(void)
{
    clear_usart1_buffer();
    send_usart1_data((uint8_t *)"AT\r\n", strlen("AT\r\n"));
    delay_ms(100);

    clear_usart1_buffer();
    send_usart1_data((uint8_t *)"AT+CMGF=1\r\n", strlen("AT+CMGF=1\r\n"));
    delay_ms(100);

    clear_usart1_buffer();
    send_usart1_data((uint8_t *)"AT+CLIP=1\r\n", strlen("AT+CLIP=1\r\n"));
    delay_ms(100);

    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}

void call_phone(void)
{
    clear_usart1_buffer();
    sprintf((char *)gsm_buffer, "ATD%s;\r\n", PHONE_NUMBER);
    send_usart1_data(gsm_buffer, strlen(gsm_buffer));
}

void hangup_phone(void)
{
    clear_usart1_buffer();
    send_usart1_data((uint8_t *)"ATH\r\n", strlen("ATH\r\n"));
}

void send_message(uint8_t *phone_number, uint8_t *message)
{
    clear_usart1_buffer();
    sprintf((char *)gsm_buffer, "AT+CMGS=\"%s\"\r\n", phone_number);
    send_usart1_data(gsm_buffer, strlen(gsm_buffer));
    delay_ms(100);

    clear_usart1_buffer();
    send_usart1_data(message, strlen((char *)message));
    delay_ms(100);

    clear_usart1_buffer();
    send_usart1_data((uint8_t *)"\x1A", strlen("\x1A"));
}

void process_incoming_call(void)
{
    clear_usart1_buffer();
    send_usart1_data((uint8_t *)"ATH\r\n", strlen("ATH\r\n")); // 先挂断当前通话
    delay_ms(1000); // 延时一段时间,等待模块处理完毕

    if (strcmp((char *)phone_number, PHONE_NUMBER) == 0) // 判断号码是否需要接听
    {
        is_calling = 1; // 表示正在通话中
        call_answered = 0; // 表示还未接听
        send_usart1_data((uint8_t *)"ATA\r\n", strlen("ATA\r\n")); // 接听电话
    }
    else
    {
        send_usart1_data((uint8_t *)"ATH\r\n", strlen("ATH\r\n")); // 挂断电话
    }
}

void EXTI9_5_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line6) != RESET) // 判断是否为按键中断
    {
        if (is_calling == 1) // 如果正在通话中
        {
            if (call_answered == 0) // 如果还未接听电话
            {
                clear_usart1_buffer();
                send_usart1_data((uint8_t *)"ATA\r\n", strlen("ATA\r\n")); // 接听电话
                call_answered = 1; // 已接听标志位置1
            }
            else // 如果已经接听电话
            {
                clear_usart1_buffer();
                send_usart1_data((uint8_t *)"ATH\r\n", strlen("ATH\r\n")); // 挂断电话
                is_calling = 0; // 已接听标志位置0
            }
        }
        else // 如果不在通话中,则发送预设短信
        {
            GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 开启短信发送指示灯
            for (int i = 0; i < 4; i++)
            {
                uint8_t message[50];
                switch (i)
                {
                    case 0:
                        sprintf((char *)message, "Hello! This is message 1.");
                        break;
                    case 1:
                        sprintf((char *)message, "Hi! How are you? This is message 2.");
                        break;
                    case 2:
                        sprintf((char *)message, "Good morning! This is message 3.");
                        break;
                    case 3:
                        sprintf((char *)message, "Good evening! This is message 4.");
                        break;
                }
                send_message(phone_number, message);
                delay_ms(5000); // 延时5s
            }
            GPIO_SetBits(GPIOA, GPIO_Pin_0); // 关闭短信发送指示灯
        }
        EXTI_ClearITPendingBit(EXTI_Line6); // 清除中断标志位
    }
}

int main(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

    GPIO_InitTypeDef gpio_init_struct;
    gpio_init_struct.GPIO_Pin = GPIO_Pin_0; // 短信发送指示灯引脚
    gpio_init_struct.GPIO_Mode = GPIO_Mode_Out_PP;
    gpio_init_struct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &gpio_init_struct);

    gpio_init_struct.GPIO_Pin = GPIO_Pin_6; // 按键引脚
    gpio_init_struct.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &gpio_init_struct);

    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource6);

    EXTI_InitTypeDef exti_init_struct;
    exti_init_struct.EXTI_Line = EXTI_Line6;
    exti_init_struct.EXTI_Mode = EXTI_Mode_Interrupt;
    exti_init_struct.EXTI_Trigger = EXTI_Trigger_Falling;
    exti_init_struct.EXTI_LineCmd = ENABLE;
    EXTI_Init(&exti_init_struct);

    NVIC_InitTypeDef nvic_init_struct;
    nvic_init_struct.NVIC_IRQChannel = EXTI9_5_IRQn;
    nvic_init_struct.NVIC_IRQChannelPreemptionPriority = 0;
    nvic_init_struct.NVIC_IRQChannelSubPriority = 0;
    nvic_init_struct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&nvic_init_struct);

    init_usart1(SIM800C_BAUDRATE);
    init_sim800c();

    while (1)
    {
        // do nothing
    }
}

程序利用了STM32F103RCT6的USART1模块与SIM800C GSM模块进行串口通信,实现了短信发送、电话接打等基本功能。

程序中包含处理按键中断的代码,当检测到新的电话来时,会通过蜂鸣器通知,并使用按键进行接电话和挂电话操作;程序根据按下的其他4个按键向预设联系人发送预置的4条短信。在主函数中,进行必要的外设初始化,然后进入一个死循环,等待中断事件的发生,例如来电、按键按下等。在接收到来电中断时,程序会判断来电号码是否是需要接听的号码,如果是,则自动接听电话;如果不是,则自动挂断电话。在按键中断中,程序会先判断是否正在通话中,如果是,则执行接听或挂断等操作;如果不是,则往预设联系人发送预置的4条短信。

四、总结

本设计实现了基于STM32F103RCT6主控芯片的简易手机系统,包括短信发送、电话接打、蜂鸣器通知、按键控制等功能。通过硬件电路的设计和制作,以及软件程序的编写和调试,实现了系统的正常工作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/36239.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【mysql】-【锁】

文章目录 概述MySQL并发事务访问相同记录读-读情况写-写情况读-写或写-读情况并发问题的解决方案 锁的不同角度分类 概述 事务的隔离性由这章讲述的锁来实现。 MySQL并发事务访问相同记录 并发事务访问相同记录的情况大致可以划分为3种: 读-读情况 读-读情况&#xff0c;…

科技力量赋予 SK5 代理 HTTP 代理 IP 网络无限可能

第一部分&#xff1a;智能网络加速技术 智能缓存&#xff1a;SK5 代理 HTTP 代理 IP 利用智能缓存技术&#xff0c;将经常访问的资源缓存在代理服务器中&#xff0c;从而实现更快速的资源加载和页面响应。这种智能化的缓存策略有效减少了对远程服务器的依赖&#xff0c;提升了用…

自建个人音乐播放器Navidrome - 内网穿透实现在外随时访问

文章目录 1. 前言2. Navidrome网站搭建2.1 Navidrome下载和安装2.1.1 安装并添加ffmpeg2.1.2下载并配置Navidrome2.1.3 添加Navidrome到系统服务 2.2. Navidrome网页测试 3. 本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4. 公网访问测试5. 结语 转…

Linux学习之vim在光标所在处写入内容,保存退出

vim insertTest使用vim打开一个叫做insertTest新文件。 输入命令之后&#xff0c;按下Enter&#xff08;回车键&#xff09;&#xff0c;就可以进入下边的操作页面。 按i在当前光标位置处&#xff0c;就可以插入内容了。 接下来写入内容跟记事本里边是差不多的。 按一下…

文心一言 VS 讯飞星火 VS chatgpt (57)-- 算法导论6.4 1题

文心一言 VS 讯飞星火 VS chatgpt &#xff08;57&#xff09;-- 算法导论6.4 1题 一、参照图 6-4 的方法&#xff0c;说明 HEAPSORT 在数组 A(5&#xff0c;13&#xff0c;2&#xff0c;25&#xff0c;7&#xff0c;17&#xff0c;20&#xff0c;8&#xff0c;4)上的操作过程…

ChatGPT显示付费墙内容,OpenAI把联网功能关了

ChatGPT 学会上网不到两个月&#xff0c;OpenAI就不能忍了。 本周二&#xff0c;OpenAI 突然宣布停止 ChatGPT 的网络浏览功能「使用 Bing 浏览」。 果不其然&#xff0c;关闭的原因是这项功能遭到了滥用。在周一发布的一篇文章中&#xff0c;OpenAI 支持团队人员表示&#xf…

微调预训练的 NLP 模型

动动发财的小手&#xff0c;点个赞吧&#xff01; 针对任何领域微调预训练 NLP 模型的分步指南 简介 在当今世界&#xff0c;预训练 NLP 模型的可用性极大地简化了使用深度学习技术对文本数据的解释。然而&#xff0c;虽然这些模型在一般任务中表现出色&#xff0c;但它们往往缺…

mac intellij idea配置settings.xml报错解决

今天在配置环境的时候&#xff0c;发现在运行代码的时候不断报错提示maven没有能够成功地被sync&#xff0c;解决方法将以下三点解决了之后&#xff0c;程序最终跑起来了。 1.将maven的版本配置对&#xff0c;之前项目都用的maven-3.8.5这个版本&#xff0c;而我原先用的是mave…

大一下暑期计划 + 2023字节青训营预告直播

目录 &#x1f33c;前言 &#x1f339;后端学习方法 &#x1f333;1&#xff0c;层次 &#x1f333;2&#xff0c;体系 &#x1f333;3&#xff0c;算法和数据结构 &#x1f333;4&#xff0c;总结 &#x1f339;前端学习方法 &#x1f333;基础 &#x1f339;求职中如…

如何在Windows 10中创建引导到UEFI固件设置的快捷方式

大多数计算机都有一个特定的键,当计算机启动时按下该键,用户可以访问UEFI(固件)设置。然而,我们经常在错过给定的时间段时按键太晚,因为笔记本电脑默认情况下只需等待几秒钟就可以启动到 Windows。 另一个引导到 UEFI 设置的选项是重新启动到高级启动选项,然后从那里开…

在linux中安装HAProxy

使用xfrp将压缩包上传到linux的opt目录下 1.解压HAProxy安装包 tar -zxvf haproxy-1.8.12.tar.gz 2. 查看点钱的内核及版本: uname -r 3. 根据内核版本选择编译参数 cd haproxy-1.8.12 cat README 4. 编译安装HAProxy make TARGETlinux2628 ARCHx86_64 PREFIX/usr/local…

Stable Diffusion - 超分辨率插件 StableSR v2 (768x768) 配置与使用

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131582734 论文&#xff1a;Exploiting Diffusion Prior for Real-World Image Super-Resolution StableSR 算法提出了一种新颖的方法&#xff0…

5、加载3dtileset模型并定位到模型

这一节使用CCesium加载3dtiles模型&#xff0c;3dtiles模型使用ceisum官网示例中的模型&#xff0c;加载3dtiles功能目前只能添加没有压缩的模型&#xff0c;draco或其他解压缩功能没有写。 1、在上一个例子的基础上&#xff0c;将鼠标事件改成右键的鼠标事件Cesium::ScreenSp…

【Web3】认识Web3

Web3是一种用于描述下一代互联网的概念 它指在构建一个去中心化 用户控制和加密安全的网络环境。 Web3的目标是将权利和数据掌握回归到用户手中 通过采用分布式技术和加密货币的支持 实现更加开放 公开和透明的互联网 Web的主要特点 去中化&#xff1a;Web3的核销理念是去中心…

【MySQL数据库】MMM高可用架构

目录 一 、MMM简介1.1MMM&#xff08;Master-Master replication manager for MvSQL&#xff0c;MySQL主主复制管理器&#xff09;1.2关于 MMM 高可用架构的说明如下 二、搭建mysql MMM架构2.1实验环境2.2搭建多主多从2.3安装配置 MySQL-MMM 一 、MMM简介 1.1MMM&#xff08;M…

安装Node.js和创建Vue-cli工程

NodeJs中文网&#xff1a;下载 | Node.js (nodejs.org) 注意事项&#xff1a; 最好下载Node16版本&#xff0c;除非你后续使用的Vue-cli版本比较高&#xff0c;像我使用的Vue-cli3和4.1.1版本去创建工程&#xff0c;然后run运行会报错Error: error:0308010C:digital envelope …

CClink IE转Modbus TCP网关连接三菱FX5U PLC

远创智控YC-CCLKIE-TCP 是自主研发的一款 CCLINK IE FIELD BASIC 从站功能的通讯网关。该产品主要功能是将各种 MODBUS-TCP 设备接入到 CCLINK IE FIELD BASIC 网络中。 远创智控YC-CCLKIE-TCP网关连接到 CCLINK IE FIELD BASIC 总线中做为从站使用&#xff0c;连接到 MODBUS-T…

uni-app 从零开始第二章:hello world

一、新建项目 选择 默认模板&#xff0c;填写项目名&#xff0c;然后点击创建&#xff0c;我这里选择的是 vue3&#xff0c;大家自行选择&#xff0c;默认是2 二、 运行项目到各个平台 注意&#xff0c;这里需要提前开启 微信开发者工具的端口 同样的&#xff0c;需要将mumu模…

将迷你世界的蓝图导出成表格

将迷你世界的蓝图导出成表格 使用方法为编译此代码&#xff0c;然后将游戏存档的vbp文件拖入编译出的exe上即可导出csv文件 #include<iostream> #include<Windows.h> #include<direct.h> #include<io.h> using namespace std; #define N_L 4 //这个改…

【大数据技术】hive 窗口函数sum range between的详细介绍

【大数据技术】hive 窗口函数sum range between的详细介绍 数据准备 建表 create table range_test( name string, month int , sales int ) row format delimited fields terminated by "," ;插入数据 load data local inpath "/home/xx/test/1.t…