【51单片机】单片机开发者的福音: 让AI看电路图帮你编写程序(使用ChatGPT 中训练好的单片机工程师模型)

简介: 使用AI大语言模型编写 单片机程序. 使用的是 OpenAI公司发布的 ChatGPT .在ChatGPT上有别人训练好的 单片机工程师 with Keil uVision 5 - C Code Explainer模型, 可以上传电路图改模型可以通过这个用户所给的电路图进行编程.


这里使用的人工智能是 OpenAI公司开发的 ChatGPT.为了让AI用起来更加的顺手我们可以选择单片机工程师这个训练好的模型,当然用原本的ChatGPT-4o也是挺好用的.

第0步 需要准备东西

1. 科学上网

2. 电路图 (可以是pdf文件\也可是高清的png或者jpg图片)

第1步 寻找一个适合自己的模型

可以点开链接直达这个模型单片机工程师 with keil uvision 5,或者登录后按照下图的方式找到这个模型.

第2步 沟通方式

公式 : 介绍+目的+要求

例子:

因为chatGPT 联系上下文的能力很强, 除了第一次沟通的时候发送文件介绍之外,在此对话的时候就可以不用发送了.就是当做一个仆人一样来对话就好, 它给我们程序,我们拿去编译 下载就好,不满足我们的要求就接着和它沟通,只要你把问题和你想要的效果描述清楚,它基本上都能完成的很好,大大提高你的工作效率.

看看这次AI的回答:

我们可以看到 , 它给出了

#include "lcd1602.h"
#include "ds1302.h"

这两个库我们是没有的,所以呢 我们具体的情况还要给ai说明白,我们没有ds1302这个芯片, 也没有lcd1602.h这个库,需要自己写

进一步说明情况

请看ai的这次回答: 我个人认为应该是没什么问题,它把lcd1602模块给单独拿来出来方便我们复用,下面是ai的回答:

好的,我们可以不使用DS1302芯片,直接在程序中预设时间信息为“23:55”,并使用定时器来模拟时间的递增。以下是修改后的完整代码,包括LCD1602的驱动程序和时间的显示功能。

LCD1602驱动程序 (lcd1602.hlcd1602.c)

lcd1602.h

#ifndef _LCD1602_H_
#define _LCD1602_H_
#include <reg51.h>
sbit RS = P2^0;  // RS引脚
sbit RW = P2^1;  // RW引脚
sbit E  = P2^2;  // E引脚
sbit D4 = P2^4;  // 数据引脚 D4
sbit D5 = P2^5;  // 数据引脚 D5
sbit D6 = P2^6;  // 数据引脚 D6
sbit D7 = P2^7;  // 数据引脚 D7
void LCD_Init(void);
void LCD_Cmd(unsigned char cmd);
void LCD_Data(unsigned char dat);
void LCD_ShowString(unsigned char x, unsigned char y, char *str);
void LCD_ShowNum(unsigned char x, unsigned char y, unsigned int num, unsigned char len);
void LCD_ShowChar(unsigned char x, unsigned char y, char ch);
#endif

lcd1602.c

#include "lcd1602.h"
// 延时函数
void Delay(unsigned int ms) {
    unsigned int i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 114; j++);
}
// 发送命令到LCD
void LCD_Cmd(unsigned char cmd) {
    RS = 0;
    RW = 0;
    E  = 1;
    D4 = cmd & 0x10;
    D5 = cmd & 0x20;
    D6 = cmd & 0x40;
    D7 = cmd & 0x80;
    E  = 0;
    E  = 1;
    D4 = cmd & 0x01;
    D5 = cmd & 0x02;
    D6 = cmd & 0x04;
    D7 = cmd & 0x08;
    E  = 0;
    Delay(2);
}
// 发送数据到LCD
void LCD_Data(unsigned char dat) {
    RS = 1;
    RW = 0;
    E  = 1;
    D4 = dat & 0x10;
    D5 = dat & 0x20;
    D6 = dat & 0x40;
    D7 = dat & 0x80;
    E  = 0;
    E  = 1;
    D4 = dat & 0x01;
    D5 = dat & 0x02;
    D6 = dat & 0x04;
    D7 = dat & 0x08;
    E  = 0;
    Delay(2);
}
// 初始化LCD1602
void LCD_Init(void) {
    LCD_Cmd(0x02);  // 初始化指令
    LCD_Cmd(0x28);  // 4位数据接口, 2行显示, 5x7点阵
    LCD_Cmd(0x0C);  // 显示开,光标关
    LCD_Cmd(0x06);  // 数据输入后,光标右移
    LCD_Cmd(0x01);  // 清屏
}
// 显示字符串
void LCD_ShowString(unsigned char x, unsigned char y, char *str) {
    unsigned char addr;
    if (y == 0)
        addr = 0x80 + x;
    else
        addr = 0xC0 + x;
    LCD_Cmd(addr);
    while (*str)
        LCD_Data(*str++);
}
// 显示数字
void LCD_ShowNum(unsigned char x, unsigned char y, unsigned int num, unsigned char len) {
    unsigned char t, temp;
    unsigned char show_flag = 0;
    for (t = 0; t < len; t++) {
        temp = (num / 10000) % 10;
        if (show_flag == 0 && t < len - 1) {
            if (temp == 0)
                LCD_Data(' ');
            else {
                show_flag = 1;
                LCD_Data(temp + '0');
            }
        } else
            LCD_Data(temp + '0');
        num *= 10;
    }
}
// 显示单个字符
void LCD_ShowChar(unsigned char x, unsigned char y, char ch) {
    unsigned char addr;
    if (y == 0)
        addr = 0x80 + x;
    else
        addr = 0xC0 + x;
    LCD_Cmd(addr);
    LCD_Data(ch);
}

主程序 (main.c)

#include <reg51.h>
#include "lcd1602.h"
// 定义全局变量来存储时间
unsigned char hour = 23, minute = 55, second = 0;
// 定时器中断函数,每1秒调用一次
void Timer0_ISR(void) interrupt 1 {
    TH0 = 0xFC;  // 重装载定时器初值
    TL0 = 0x18;
    
    second++;
    if (second == 60) {
        second = 0;
        minute++;
        if (minute == 60) {
            minute = 0;
            hour++;
            if (hour == 24)
                hour = 0;
        }
    }
}
// 定时器0初始化
void Timer0_Init() {
    TMOD = 0x01;  // 设置定时器0为模式1(16位定时器)
    TH0 = 0xFC;   // 设置定时器初值,使得1秒触发一次中断
    TL0 = 0x18;
    ET0 = 1;      // 使能定时器0中断
    EA  = 1;      // 使能总中断
    TR0 = 1;      // 启动定时器0
}
void main() {
    LCD_Init();      // 初始化LCD1602
    Timer0_Init();   // 初始化定时器
    while(1) {
        // 在LCD1602上显示时间
        LCD_ShowString(0, 0, "Time:");
        LCD_ShowNum(5, 0, hour, 2);   // 显示小时
        LCD_ShowChar(7, 0, ':');
        LCD_ShowNum(8, 0, minute, 2); // 显示分钟
        LCD_ShowChar(10, 0, ':');
        LCD_ShowNum(11, 0, second, 2); // 显示秒
        
        Delay(1000);  // 刷新间隔
    }
}

说明:

  1. LCD1602驱动lcd1602.hlcd1602.c文件实现了LCD1602的初始化和显示功能,包括显示字符串、数字和单个字符。
  2. 定时器模拟时钟:定时器0的中断每秒触发一次,用于更新秒、分钟和小时变量,并将其显示在LCD1602上。
  3. 程序结构:主程序通过循环不断更新LCD1602上的时间显示。

编译和运行:

  1. 将上述代码分别保存到lcd1602.hlcd1602.cmain.c中。
  2. 使用Keil uVision 5进行编译并将程序下载到开发板上。
  3. 观察LCD1602上显示的时间变化。

这个程序将在开始时显示"23:55",然后每秒自动递增,模拟时钟功能。

总之它给程序,你就拿到你的板子上进行调试即可,还不满意你就让它改.

但是由于你不是plus用户, 用多了可能就回出现(提醒你该充钱或者切换账号)

没钱有没钱的办法,可以使用 copilot 请看这篇文章【51单片机】让AI识别电路图,帮你进行编码(以51单片机为例)


这是我让AI实现的万年历功能,阅读代码其实我们不难看出ai的创造性思维是不如人类的, 就比如它不知道如何把独立按键发挥到极致,让时间日期数值可以增加可以减小,程序中它只有增加没有减小的逻辑,对用户来说体验感就大打折扣.我们能做的就是继续和它沟通完善程序,或者自己修改程序.

要实现一个万年历功能,显示时间和日期,并且可以通过独立按键修改时间和日期,需要按照以下步骤进行设计和实现。这个程序将使用8051单片机、LCD1602显示屏、以及独立按键来实现时间和日期的显示和调整。

功能实现概要:

  1. 显示内容:在LCD1602上显示当前的日期和时间。
  2. 时间日期初始化:初始时间为2024年8月15日16:19:15。
  3. 时间更新:使用定时器中断每秒更新一次时间。
  4. 独立按键调整时间日期:使用三个独立按键分别调整小时、分钟和日期。

硬件连接假设:

  • LCD1602:数据线接P2口,控制线RS、RW、E分别接P2.0、P2.1、P2.2。
  • 按键:三个独立按键分别接P3.0(调整小时)、P3.1(调整分钟)、P3.2(调整日期)。

万年历功能代码

lcd1602.h

#ifndef _LCD1602_H_
#define _LCD1602_H_
#include <reg51.h>
sbit RS = P2^0;  // RS引脚
sbit RW = P2^1;  // RW引脚
sbit E  = P2^2;  // E引脚
sbit D4 = P2^4;  // 数据引脚 D4
sbit D5 = P2^5;  // 数据引脚 D5
sbit D6 = P2^6;  // 数据引脚 D6
sbit D7 = P2^7;  // 数据引脚 D7
void LCD_Init(void);
void LCD_Cmd(unsigned char cmd);
void LCD_Data(unsigned char dat);
void LCD_ShowString(unsigned char x, unsigned char y, char *str);
void LCD_ShowNum(unsigned char x, unsigned char y, unsigned int num, unsigned char len);
void LCD_ShowChar(unsigned char x, unsigned char y, char ch);
#endif

lcd1602.c

#include "lcd1602.h"
// 延时函数
void Delay(unsigned int ms) {
    unsigned int i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 114; j++);
}
// 发送命令到LCD
void LCD_Cmd(unsigned char cmd) {
    RS = 0;
    RW = 0;
    E  = 1;
    D4 = cmd & 0x10;
    D5 = cmd & 0x20;
    D6 = cmd & 0x40;
    D7 = cmd & 0x80;
    E  = 0;
    E  = 1;
    D4 = cmd & 0x01;
    D5 = cmd & 0x02;
    D6 = cmd & 0x04;
    D7 = cmd & 0x08;
    E  = 0;
    Delay(2);
}
// 发送数据到LCD
void LCD_Data(unsigned char dat) {
    RS = 1;
    RW = 0;
    E  = 1;
    D4 = dat & 0x10;
    D5 = dat & 0x20;
    D6 = dat & 0x40;
    D7 = dat & 0x80;
    E  = 0;
    E  = 1;
    D4 = dat & 0x01;
    D5 = dat & 0x02;
    D6 = dat & 0x04;
    D7 = dat & 0x08;
    E  = 0;
    Delay(2);
}
// 初始化LCD1602
void LCD_Init(void) {
    LCD_Cmd(0x02);  // 初始化指令
    LCD_Cmd(0x28);  // 4位数据接口, 2行显示, 5x7点阵
    LCD_Cmd(0x0C);  // 显示开,光标关
    LCD_Cmd(0x06);  // 数据输入后,光标右移
    LCD_Cmd(0x01);  // 清屏
}
// 显示字符串
void LCD_ShowString(unsigned char x, unsigned char y, char *str) {
    unsigned char addr;
    if (y == 0)
        addr = 0x80 + x;
    else
        addr = 0xC0 + x;
    LCD_Cmd(addr);
    while (*str)
        LCD_Data(*str++);
}
// 显示数字
void LCD_ShowNum(unsigned char x, unsigned char y, unsigned int num, unsigned char len) {
    unsigned char t, temp;
    unsigned char show_flag = 0;
    for (t = 0; t < len; t++) {
        temp = (num / 10000) % 10;
        if (show_flag == 0 && t < len - 1) {
            if (temp == 0)
                LCD_Data(' ');
            else {
                show_flag = 1;
                LCD_Data(temp + '0');
            }
        } else
            LCD_Data(temp + '0');
        num *= 10;
    }
}
// 显示单个字符
void LCD_ShowChar(unsigned char x, unsigned char y, char ch) {
    unsigned char addr;
    if (y == 0)
        addr = 0x80 + x;
    else
        addr = 0xC0 + x;
    LCD_Cmd(addr);
    LCD_Data(ch);
}

主程序 (main.c)

#include <reg51.h>
#include "lcd1602.h"
// 定义引脚
sbit Key1 = P3^0;  // 调整小时
sbit Key2 = P3^1;  // 调整分钟
sbit Key3 = P3^2;  // 调整日期
// 时间和日期变量
unsigned int year = 2024;
unsigned char month = 8, day = 15, hour = 16, minute = 19, second = 15;
// 检测按键按下状态的函数
bit Key_Pressed(sbit key) {
    if (!key) {      // 如果按键被按下
        Delay(20);   // 消抖延时
        if (!key) {  // 确认按下
            while (!key);  // 等待按键释放
            return 1;
        }
    }
    return 0;
}
// 更新时间函数
void Update_Time() {
    second++;
    if (second == 60) {
        second = 0;
        minute++;
        if (minute == 60) {
            minute = 0;
            hour++;
            if (hour == 24) {
                hour = 0;
                day++;
                // 判断每月天数
                if ((month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) && day == 32) {
                    day = 1;
                    month++;
                } else if ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) {
                    day = 1;
                    month++;
                } else if (month == 2 && (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)) { // 闰年
                    if (day == 30) {
                        day = 1;
                        month++;
                    }
                } else if (month == 2 && day == 29) {
                    day = 1;
                    month++;
                }
                if (month == 13) {
                    month = 1;
                    year++;
                }
            }
        }
    }
}
// 定时器中断函数,每1秒调用一次
void Timer0_ISR(void) interrupt 1 {
    TH0 = 0xFC;  // 重装载定时器初值
    TL0 = 0x18;
    
    Update_Time();
}
// 定时器0初始化
void Timer0_Init() {
    TMOD = 0x01;  // 设置定时器0为模式1(16位定时器)
    TH0 = 0xFC;   // 设置定时器初值,使得1秒触发一次中断
    TL0 = 0x18;
    ET0 = 1;      // 使能定时器0中断
    EA  = 1;      // 使能总中断
    TR0 = 1;      // 启动定时器0
}
void main() {
    LCD_Init();      // 初始化LCD1602
    Timer0_Init();   // 初始化定时器
    while(1) {
        // 检测按键,调整时间和日期
        if (Key_Pressed(Key1)) {
            hour++;
            if (hour == 24) hour = 0;
        }
        if (Key_Pressed(Key2)) {
            minute++;
            if (minute == 60) minute = 0;
        }
        if (Key_Pressed(Key3)) {
            day++;
            // 需要根据月份判断天数
            if ((month == 1 || month == 
3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) && day == 32) {
                day = 1;
                month++;
            } else if ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) {
                day = 1;
                month++;
            } else if (month == 2 && (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)) { // 闰年
                if (day == 30) {
                    day = 1;
                    month++;
                }
            } else if (month == 2 && day == 29) {
                day = 1;
                month++;
            }
            if (month == 13) {
                month = 1;
                year++;
            }
        }
        // 在LCD1602上显示日期
        LCD_ShowString(0, 0, "Date:");
        LCD_ShowNum(5, 0, year, 4);  // 显示年份
        LCD_ShowChar(9, 0, '-');
        LCD_ShowNum(10, 0, month, 2); // 显示月份
        LCD_ShowChar(12, 0, '-');
        LCD_ShowNum(13, 0, day, 2);  // 显示日期
        
        // 在LCD1602上显示时间
        LCD_ShowString(0, 1, "Time:");
        LCD_ShowNum(5, 1, hour, 2);  // 显示小时
        LCD_ShowChar(7, 1, ':');
        LCD_ShowNum(8, 1, minute, 2); // 显示分钟
        LCD_ShowChar(10, 1, ':');
        LCD_ShowNum(11, 1, second, 2); // 显示秒
        
        Delay(100);  // 刷新间隔
    }
}

说明:

  1. LCD1602驱动lcd1602.hlcd1602.c文件实现了LCD1602的初始化和显示功能,包括显示字符串、数字和单个字符。
  2. 时间和日期更新:定时器0中断每秒触发一次,更新秒、分钟、小时、天、月和年。
  3. 按键调整:三个独立按键分别用于调整小时、分钟和日期。
  4. 闰年判断:程序中对2月份日期进行了闰年的判断和处理。
  5. 程序结构:主程序通过循环不断检测按键输入,并在LCD1602上实时更新日期和时间显示。

编译和运行:

  1. 将上述代码分别保存到lcd1602.hlcd1602.cmain.c中。
  2. 使用Keil uVision 5进行编译,并将程序下载到开发板上。
  3. 通过按键调整时间和日期,并观察LCD1602上显示的结果。

这个程序实现了一个简单的万年历功能,可以显示时间和日期,并且通过按键进行调整。你可以根据需求进一步修改或扩展功能。

当然,AI对程序某个部分的驱动其实是值得我们学习的, 比如按键消抖和lcd1602的驱动等等。如果你是初学的你可能很难理解按键消抖,也很难理解LCD1602的时序图,然后对着时序图 读状态 写指令 读数据 写数据。 这东西对曾经只想完成老师作业的我来说简直就是一种折磨。

相关文章
|
4天前
|
人工智能 自然语言处理 前端开发
Trae插件Builder模式深度测评:从编程助手到AI工程师的进化
Trae插件最新推出的Builder模式标志着AI辅助编程工具从简单的代码补全向“AI工程师”角色的转变。该模式允许开发者通过自然语言描述项目需求,自动生成完整的项目结构、代码文件和开发流程,支持VSCode、JetBrains IDE及在线Web版本。Builder模式的核心功能包括自然语言项目初始化、智能项目架构设计和多文件协调代码生成,显著提升了开发效率,降低了技术门槛。然而,它在处理复杂业务逻辑和高度定制化需求方面仍有局限。未来,Builder模式将集成云部署、测试套件生成和DevOps流水线等功能
178 1
|
12天前
|
数据采集 存储 人工智能
智创 AI 新视界 -- 优化 AI 模型训练效率的策略与技巧(16 - 1)
本文深度聚焦 AI 模型训练效率优化,全面涵盖数据预处理(清洗、归一化、增强)、模型架构(轻量级应用、剪枝与量化)、训练算法与超参数调优(自适应学习率、优化算法)等核心维度。结合自动驾驶、动物图像识别、语音识别等多领域实际案例,佐以丰富且详细的代码示例,深度剖析技术原理与应用技巧,为 AI 从业者呈上极具专业性、可操作性与参考价值的技术宝典,助力高效优化模型训练效率与性能提升。
智创 AI 新视界 -- 优化 AI 模型训练效率的策略与技巧(16 - 1)
|
7天前
|
人工智能 自然语言处理 安全
💻 Codex 来了:OpenAI 推出多任务软件工程 AI 代理,开发者工作方式将被重塑?
Codex 是 OpenAI 推出的一款云端智能开发代理,基于优化后的 Codex-1 模型,能够执行从代码编写、Bug 修复到 PR 提交的完整工程任务。通过 ChatGPT 的界面,用户可向 Codex 分配任务,它将在独立沙盒中运行并返回结果。Codex 支持多任务异步处理,遵循项目规范(AGENTS.md),并生成日志与测试报告以确保透明性。作为“AI 参与式开发”的里程碑,Codex 不仅提升效率,还可能重塑开发者角色,使他们从具体编码转向指导 AI 完成任务,推动软件工程进入意图驱动的新时代。
103 15
|
1月前
|
人工智能 自然语言处理 JavaScript
测试工程师要失业?Magnitude:开源AI Agent驱动的端到端测试框架,让Web测试更智能,自动完善测试用例!
Magnitude是一个基于视觉AI代理的开源端到端测试框架,通过自然语言构建测试用例,结合推理代理和视觉代理实现智能化的Web应用测试,支持本地运行和CI/CD集成。
253 15
测试工程师要失业?Magnitude:开源AI Agent驱动的端到端测试框架,让Web测试更智能,自动完善测试用例!
|
1月前
|
人工智能 供应链 Cloud Native
中国AI编码工具崛起:技术突围、生态重构与开发者新范式
中国AI编码工具如通义灵码、百度Comate等,正从西方产品的主导中突围。通过大模型精调、中文友好型理解及云原生赋能,构建差异化优势。这些工具不仅提升效率,还推动中国软件产业从使用者向标准制定者转变。然而,技术原创性、生态碎片化和开发者信任危机仍是挑战。未来目标不是取代现有工具,而是定义适合中国开发者的智能编码新范式。
120 24
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
FinGPT:华尔街颤抖!用股价训练AI,开源金融大模型预测股价准确率碾压分析师,量化交易新利器
FinGPT是基于Transformer架构的开源金融大模型,通过RLHF技术和实时数据处理能力,支持情感分析、市场预测等核心功能,其LoRA微调技术大幅降低训练成本。
164 12
FinGPT:华尔街颤抖!用股价训练AI,开源金融大模型预测股价准确率碾压分析师,量化交易新利器
|
1月前
|
人工智能 安全 测试技术
通义灵码:AI重构编码范式,开发者如何迎接“人机共生”时代?
本文探讨了以通义灵码为代表的AI编码助手如何推动软件开发从“人驱动工具”向“人机协同创造”演进。文章分析了其技术突破,如意图理解、上下文感知和可解释性,并讨论了开发者价值链条的重构,包括需求抽象、架构设计与代码审查能力的提升。同时,文章展望了行业变革对开发者身份、云生态竞争及技术伦理的影响,强调在AI驱动的“寒武纪大爆发”前夜,唯有持续进化才能适应未来软件工程的“人机共生”文明。
122 16
|
1月前
|
人工智能 算法 IDE
通义灵码:以AI重塑开发者生产力,解锁智能编程新范式
通义灵码是阿里云推出的一款AI智能编程助手,基于通义大模型打造,深度集成于主流IDE。它不仅提供全场景智能代码生成、对话式开发体验和工程化智能重构等功能,还通过百亿级参数大模型底座、企业级环境适配、私有化部署等优势,重新定义人机协作边界。在真实开发场景中,通义灵码显著提升API开发与算法优化效率,助力开发者从机械劳动转向创造性对话,开启人机协同的新时代。
114 9
|
1月前
|
人工智能 自然语言处理 Java
通义灵码:AI编程助手如何重塑开发者的效率革命?
通义灵码是阿里云推出的一款基于通义大模型的智能编程助手,支持Java、Python、Go等主流语言,并深度适配VSCode、JetBrains等开发环境。其核心功能包括自然语言转代码、跨文件上下文理解、行级/函数级实时补全、自动生成单元测试及性能优化建议等。此外,还提供知识问答引擎、文档智能生成和研发大数据分析等进阶功能,助力开发者提升效率。通过重构生产关系,将重复劳动转化为创造性工作,使技术债务可视化,推动人机协同编程新时代的到来。
135 1
|
1月前
|
机器学习/深度学习 人工智能 算法
AI编程工具与初级开发者:一场「替代」还是「共生」的讨论
当AI编程工具从科幻走进现实,初级开发者究竟会成为技术革命的牺牲品,还是新一轮生产力跃迁的受益者?

热门文章

最新文章