【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的时序图,然后对着时序图 读状态 写指令 读数据 写数据。 这东西对曾经只想完成老师作业的我来说简直就是一种折磨。

相关文章
|
1月前
|
机器学习/深度学习 人工智能 并行计算
"震撼!CLIP模型:OpenAI的跨模态奇迹,让图像与文字共舞,解锁AI理解新纪元!"
【10月更文挑战第14天】CLIP是由OpenAI在2021年推出的一种图像和文本联合表示学习模型,通过对比学习方法预训练,能有效理解图像与文本的关系。该模型由图像编码器和文本编码器组成,分别处理图像和文本数据,通过共享向量空间实现信息融合。CLIP利用大规模图像-文本对数据集进行训练,能够实现zero-shot图像分类、文本-图像检索等多种任务,展现出强大的跨模态理解能力。
98 2
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
当语言遇见智慧火花:GPT家族历代模型大起底,带你见证从平凡到卓越的AI进化奇迹!
【10月更文挑战第6天】随着自然语言处理技术的进步,GPT系列模型(Generative Pre-trained Transformers)成为该领域的明星。从GPT-1的开创性工作,到GPT-2在规模与性能上的突破,再到拥有1750亿参数的GPT-3及其无需微调即可执行多种NLP任务的能力,以及社区驱动的GPT-NeoX,这些模型不断进化。虽然它们展现出强大的语言理解和生成能力,但也存在如生成错误信息或偏见等问题。本文将对比分析各代GPT模型的特点,并通过示例代码展示其部分功能。
114 2
|
25天前
|
人工智能
AI科学家太多,谁靠谱一试便知!普林斯顿新基准CORE-Bench:最强模型仅有21%准确率
【10月更文挑战第21天】普林斯顿大学研究人员提出了CORE-Bench,一个基于计算可重复性的AI代理基准,涵盖计算机科学、社会科学和医学领域的270个任务。该基准旨在评估AI代理在科学研究中的准确性,具有多样性、难度级别和现实相关性等特点,有助于推动AI代理的发展并提高计算可重复性。
42 4
|
1月前
|
人工智能 自然语言处理
从迷茫到精通:揭秘模型微调如何助你轻松驾驭AI新热点,解锁预训练模型的无限潜能!
【10月更文挑战第13天】本文通过简单的问题解答形式,结合示例代码,详细介绍了模型微调的全流程。从选择预训练模型、准备新任务数据集、设置微调参数,到进行微调训练和评估调优,帮助读者全面理解模型微调的技术细节和应用场景。
71 6
|
1月前
|
人工智能 自然语言处理 安全
【通义】AI视界|Adobe推出文生视频AI模型,迎战OpenAI和Meta
本文精选了过去24小时内的重要科技新闻,包括微软人工智能副总裁跳槽至OpenAI、Adobe推出文本生成视频的AI模型、Meta取消高端头显转而开发超轻量设备、谷歌与核能公司合作为数据中心供电,以及英伟达股价创下新高,市值接近3.4万亿美元。这些动态展示了科技行业的快速发展和激烈竞争。点击链接或扫描二维码获取更多资讯。
|
1月前
|
人工智能 开发框架 搜索推荐
AI 骁龙 PC 开发者 技术 沙龙
AI 骁龙 PC 开发者 技术 沙龙
32 1
|
1月前
|
机器学习/深度学习 人工智能 TensorFlow
解锁AI潜力:让开源模型在私有环境绽放——手把手教你搭建专属智能服务,保障数据安全与性能优化的秘密攻略
【10月更文挑战第8天】本文介绍了如何将开源的机器学习模型(如TensorFlow下的MobileNet)进行私有化部署,包括环境准备、模型获取与转换、启动TensorFlow Serving服务及验证部署效果等步骤,适用于希望保护用户数据并优化服务性能的企业。
53 4
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
揭开模型微调Fine-Tuning的神秘面纱:如何在预训练基础上巧妙调整,解锁定制AI解决方案的秘密武器
【10月更文挑战第8天】模型微调是在预训练模型基础上,利用特定领域数据进一步训练,以优化模型在特定任务上的表现。此方法广泛应用于自然语言处理和计算机视觉等领域,通过调整预训练模型的部分或全部参数,结合适当的正则化手段,有效提升模型性能。例如,使用Hugging Face的Transformers库对BERT模型进行微调,以改善文本匹配任务的准确率。
57 1
|
8天前
|
机器学习/深度学习 人工智能 自然语言处理
当前AI大模型在软件开发中的创新应用与挑战
2024年,AI大模型在软件开发领域的应用正重塑传统流程,从自动化编码、智能协作到代码审查和测试,显著提升了开发效率和代码质量。然而,技术挑战、伦理安全及模型可解释性等问题仍需解决。未来,AI将继续推动软件开发向更高效、智能化方向发展。
|
13天前
|
机器学习/深度学习 人工智能 自然语言处理
AI在医疗领域的应用及其挑战
【10月更文挑战第34天】本文将探讨人工智能(AI)在医疗领域的应用及其面临的挑战。我们将从AI技术的基本概念入手,然后详细介绍其在医疗领域的各种应用,如疾病诊断、药物研发、患者护理等。最后,我们将讨论AI在医疗领域面临的主要挑战,包括数据隐私、算法偏见、法规合规等问题。
37 1
下一篇
无影云桌面