前言:
我的想法是搭建一个和STM32cubemux类似的图形化代码生成工具,可以把我平时用到的代码整合一下全部放入这个软件中,做一个我自己专门的代码生成工具,我初步的想法是在下拉选框中拉取需要配置的功能,然后就弹出对应的脚位图,只需要点击芯片上的脚位就可以配置对应的端口的功能,大家有好的建议欢迎指正。本工具实时更新到完成为止,我会实时更新进度和制作中遇到的问题和想法。
1.界面编写
界面大概框架布局,
界面的搭建可以参考下面链接的教程
- 搭建好后,首先实现新建文件,保存文件,打开文件对应的功能。
选择新建动作,右击点击转到槽
选择
triggered()//
触发时机:当用户通过点击、快捷键等方式显式触发动作时(例如点击菜单项或工具栏按钮)
会在mainwindow.cpp自动生成一个槽函数
我们在该该函数里写上新建的代码
void MainWindow::on_action_N_triggered() { // 弹出文件对话框,让用户选择保存路径和文件名 QString fileName = QFileDialog::getSaveFileName( this, "保存文件", QDir::homePath(), // 默认保存到用户主目录 "文本文件 (*.c);;所有文件 (*)" ); if (fileName.isEmpty()) { QMessageBox::warning(this, "警告", "未选择文件名!"); return; } // 使用 QFile 创建文件 QFile file(fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream stream(&file); stream << "这是一个新创建的文件\n"; // 写入初始内容 file.close(); QMessageBox::information(this, "成功", "文件已创建:" + fileName); } else { QMessageBox::critical(this, "错误", "无法创建文件:" + fileName); } }
就实现了新建的功能
然后实现保存功能
点击保存动作右击转到槽
选择
triggered()
在槽函数里写上保存的代码,现在保存的是TextEdit控件中的文本,之后再进行调整
void MainWindow::on_saveButton_clicked() { // 弹出文件保存对话框 QString fileName = QFileDialog::getSaveFileName( this, "保存文件", QDir::homePath(), "文本文件 (*.txt);;所有文件 (*)" ); if (fileName.isEmpty()) { QMessageBox::warning(this, "警告", "未选择保存路径!"); return; } // 打开文件并写入 QTextEdit 的内容 QFile file(fileName); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream stream(&file); stream << ui->textEdit->toPlainText(); // 获取 QTextEdit 的文本内容 file.close(); QMessageBox::information(this, "成功", "文件已保存!"); } else { QMessageBox::critical(this, "错误", "无法保存文件!"); } }
我们先来设置主要的功能,就是点击配置选项的多选框,自动弹出芯片,并标出可选配置的脚位
下拉选项条转到槽填上以下代码
一.弹出窗口,和窗口自动跟随主窗口
void MainWindow::on_comboBox_activated(int index)//芯片选择
{
// 获取当前选项的图片路径标识
QString imageName = ui->comboBox->itemData(index).toString();
// 假设图片存放在可执行文件同级目录的 images 文件夹下
QString imagePath = ":/myimages/MCU/" + imageName;
// 加载图片
QPixmap pixmap(imagePath);
if (pixmap.isNull()) {
qDebug() << "无法加载图片:" << imagePath;
ui-> picture->setText("图片加载失败");
return;
}
// 显示图片(自动缩放适应 QLabel)
ui->picture->setPixmap(pixmap.scaled(ui->picture->size(), Qt::KeepAspectRatio));
}
然后初始化下拉框的值
ui->comboBox->addItem("SC8P052", "SC8P052.png");
ui->comboBox->addItem("SC8P054", "SC8P054.png");
ui->comboBox->addItem("SC8P054_16A", "SC8P054_16A.png");
ui->comboBox->addItem("SC8P062BD", "SC8P062BD.png");
ui->comboBox->addItem("SC8P062BD_14A", "SC8P062BD_14A.png");
ui->comboBox->addItem("SC8P8022D", "SC8P8022D.png");
ui->comboBox->addItem("SC8P8122", "SC8P8122.png");
ui->comboBox->addItem("MC30P6250", "MC30P6250.png");
ui->comboBox->addItem("MC30P6280", "MC30P6280.png");
ui->comboBox->addItem("P02", "P02.png");
ui->comboBox->addItem("P04", "P04.png");
ui->comboBox->addItem("SC8F073", "SC8F073.png");
ui->comboBox->addItem("SC8F073_16A", "SC8F073_16A.png");
这是导入的图片文件
如何导入看这篇文章
我的设置完后,选择哪个芯片就会弹出对应的芯片脚位图
但是出来的图片有些模糊,可能是拉伸的比列不对,直接显示在界面上也有点占空间,我们把它变为浮窗的模式,下面是没有修改前的模式
创建一个新的界面,用来显示浮窗
FloatImageDialog.h.h文件
#ifndef FLOATIMAGEDIALOG_H
#define FLOATIMAGEDIALOG_H
#include <QDialog>
#include <QLabel>
#include <QPixmap>
class FloatImageDialog : public QDialog
{
Q_OBJECT
public:
explicit FloatImageDialog(const QString &imagePath, QWidget *parent = nullptr);
~FloatImageDialog();
private:
QLabel *imageLabel; // 用于显示图片的标签
};
#endif // FLOATIMAGEDIALOG_H
FloatImageDialog.cpp文件
#include "FloatImageDialog.h"
#include <QVBoxLayout>
#include <QPushButton>
#include <QMouseEvent> //
FloatImageDialog::FloatImageDialog(const QString &imagePath, QWidget *parent)
: QDialog(parent)
{
// 设置窗口属性:无边框、置顶、透明背景(可选)
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
setAttribute(Qt::WA_TranslucentBackground); // 如果需要透明背景
// 加载图片
QPixmap pixmap(imagePath);
if (pixmap.isNull()) {
qDebug() << "无法加载图片:" << imagePath;
return;
}
// 创建控件
imageLabel = new QLabel(this);
imageLabel->setPixmap(pixmap.scaled(400, 400, Qt::KeepAspectRatio, Qt::SmoothTransformation));
// 可选:添加关闭按钮
QPushButton *closeButton = new QPushButton("关闭", this);
connect(closeButton, &QPushButton::clicked, this, &FloatImageDialog::close);
// 布局
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(imageLabel);
layout->addWidget(closeButton);
}
FloatImageDialog::~FloatImageDialog() {}
void FloatImageDialog::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
dragPosition = event->globalPos() - frameGeometry().topLeft();
event->accept();
}
}
void FloatImageDialog::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
move(event->globalPos() - dragPosition);
event->accept();
}
}
主函数MainWindow.h中加入头文件
#include "FloatImageDialog.h" // 包含自定义对话框头文件
转到用来隐藏显示MCU的槽函数
写入以下代码
if (!floatDialog) {
// 创建浮动窗口(传入图片资源路径)
floatDialog = new FloatImageDialog(":/images/SC8P052.png", this);
floatDialog->show();
} else {
// 关闭并释放浮动窗口
floatDialog->close();
delete floatDialog;
floatDialog = nullptr;
}
实现了芯片图片在另一个窗口显示并可以拖动
给它初始化固定在右侧,用以下代码时不要忘记头文件#include <QScreen>
void MainWindow::onToggleFloatWindow()
{
if (!floatDialog) {
// 创建浮动窗口
floatDialog = new FloatImageDialog(":/images/SC8P052.png", this);
// 获取主窗口的屏幕位置和尺寸
QRect mainGeometry = this->geometry();
// 计算浮动窗口的初始位置(主窗口右侧 + 10 像素)
int x = mainGeometry.right() + 10;
int y = mainGeometry.top();
// 获取屏幕的可用区域(避免窗口超出屏幕)
QScreen *screen = QGuiApplication::primaryScreen();
QRect screenGeometry = screen->availableGeometry();
// 如果浮动窗口超出屏幕右侧,调整到屏幕边缘
int maxX = screenGeometry.right() - floatDialog->width();
if (x > maxX) {
x = maxX;
}
// 设置浮动窗口位置
floatDialog->move(x, y);
floatDialog->show();
} else {
// 关闭并释放浮动窗口
floatDialog->close();
delete floatDialog;
floatDialog = nullptr;
}
}
窗口跟随移动
// MainWindow.h
protected:
void moveEvent(QMoveEvent *event) override;
// MainWindow.cpp
void MainWindow::moveEvent(QMoveEvent *event)
{
QMainWindow::moveEvent(event);
if (floatDialog) {
// 主窗口移动时更新浮动窗口位置
QRect mainGeometry = geometry();
int x = mainGeometry.right() + 10;
int y = mainGeometry.top();
floatDialog->move(x, y);
}
}
加更:
对界面进行了修改
原本想的是MCU选型完之后,根据不同的芯片,引脚的不同,跳转出相应的芯片,然后发现有点麻烦,我现在是直接把最大引脚的芯片放上来,如果是八脚的芯片就只用看上半部分,之后如果有时间再进行优化,现在的首要任务是把程序的功能先给实现。
我们新建一个专门用来填写,可以选择引脚功能的一个类。为了实现方便扩展,我们还要建一个读取文件的类,负责把各种芯片的引脚信息放在里面,程序来读取不同芯片引脚的功能。
二.文件读取类
cpp文件:
#include "FileHandler.h"
#include <QFile>
#include <QTextStream>
#include <QCoreApplication>
FileHandler::FileHandler(QObject *parent) : QObject(parent)
{
// 构造函数初始化(可留空)<button class="citation-flag" data-index="7">
}
QString FileHandler::readTextFile(const QString &filePath)
{
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "读取失败:" << file.errorString(); // 错误处理 <button class="citation-flag" data-index="6">
return QString();
}
QTextStream in(&file);
QString content = in.readAll(); // 读取全部内容 <button class="citation-flag" data-index="5">
file.close();
return content;
}
bool FileHandler::writeTextFile(const QString &filePath, const QString &content)
{
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
emit writeCompleted(false); // 触发信号 <button class="citation-flag" data-index="6">
return false;
}
QTextStream out(&file);
out << content; // 写入内容 <button class="citation-flag" data-index="5">
file.close();
emit writeCompleted(true);
return true;
}
.h文件
#ifndef FILEHANDLER_H
#define FILEHANDLER_H
#include <QObject>
#include <QString>
#include <QByteArray>
class FileHandler : public QObject
{
Q_OBJECT
public:
explicit FileHandler(QObject *parent = nullptr);
// 同步读取文本文件
static QString readTextFile(const QString &filePath); // 声明静态方法 <button class="citation-flag" data-index="4">
// 异步写入文件(带信号)
bool writeTextFile(const QString &filePath, const QString &content);
signals:
void writeCompleted(bool success); // 自定义信号 <button class="citation-flag" data-index="6">
private:
// 可添加私有辅助方法
};
#endif // FILEHANDLER_H
使用
QString data = FileHandler::readTextFile(":/MCU/DATA/MCU_IO/SC8P052.txt");
qDebug() << "文件内容:" << data;
文件格式定义:
我们把芯片每个引脚的功能按以下格式写入txt文件。
PIN 16 P01 VDD P02 RB0 CMP2- OSCIN AN8 PWMD0 P03 RB1 CMP1- OSCOUT AN9 PWMB4 PWMD1 P04 RB2 AN10 PWMB3 PWMD4 P05 RB3 AN11 PWMD2 P06 RB4 AN12 PWMC4 PWMD3 P07 RB5 PWMC3 AN13 P08 RB6 PWMC2 AN14 P09 RB7 AN15 PWMC1 P10 RA5 AN5 PWMC0 P11 RA4 AN4 PWMA4 P12 RA3 AN3 PWMA3 P13 RA2 AN2 PWMA2 PWMB2 CMP0- P14 RA1 AN1 PWMA1 PWMB1 CMP+ CMP3 P15 RA0 AN0 PWMA0 PWMB0 CMPO INT P16 GND
QString data = FileHandler::readTextFile(":/MCU/DATA/MCU_IO/"+imagePath+".txt");
qDebug() << "文件内容:" << data;
把这串代码放入槽函数中
在调试窗口可以看到文件正常的读出
现在我们要做的是把读到的文件,放入到数组当中,然后把数组里的每个引脚的可以设置的功能写到相应的combobox当中。
在调试的工程中,发现在别的类当中无法直接操作combobox,所以转来转去最后还是把操作combobox的代码写在了mainwindow当中,原本想直接在另外一个类中实现的,现在是通过信号和槽函数进行链接。
三.芯片引脚功能填充
主函数里加入的代码
mainwindow.cpp
// MainWindow.cpp
void MainWindow::parsePinData(const QString &data) {
clearAllComboboxes();
QStringList lines = data.split('\n', Qt::SkipEmptyParts);
int pin = 0;
QMap<QString, QString> pinMap;
foreach (const QString &line, lines) {
if (line.startsWith("PIN")) {
QRegularExpression rx("PIN (\\d+)");
QRegularExpressionMatch match = rx.match(line);
if (match.hasMatch()) {
pin = match.captured(1).toInt();
pinMap = getPinMap(pin);
}
} else {
QStringList parts = line.split(' ', Qt::SkipEmptyParts);
if (parts.size() < 2) continue;
QString srcPin = parts[0];
QStringList items = parts.mid(1);
QString targetPin = pinMap.value(srcPin, "");
if (targetPin.isEmpty()) continue;
// 直接访问 MainWindow 的控件
QComboBox *combo = findChild<QComboBox*>(targetPin);
if (combo) {
combo->clear();
combo->addItems(items);
}
}
}
}
void MainWindow::clearAllComboboxes() {
QList<QComboBox*> combos = findChildren<QComboBox*>();
foreach (QComboBox *combo, combos) {
if (combo->objectName().startsWith("P")) {
combo->clear();
}
}
}
QMap<QString, QString> MainWindow::getPinMap(int pin) {
QMap<QString, QString> map;
if (pin == 8) {
map = {
{"P01", "P01"}, {"P02", "P02"}, {"P03", "P03"}, {"P04", "P04"},
{"P05", "P13"}, {"P06", "P14"}, {"P07", "P15"}, {"P08", "P06"}
};
} else if (pin == 14) {
map = { /* ... */ };
} else if (pin == 16) {
for (int i = 1; i <= 16; ++i) {
QString key = QString("P%1").arg(i, 2, 10, QLatin1Char('0'));
map[key] = key;
}
}
return map;
}
// MainWindow.h
public: // 或 public slots:
void parsePinData(const QString &data);
ConfigComboBox.cpp
void ConfigComboBox::setcombobox(QString &imageName)
{
// if(imagePath=="SC8P052")
// {
// 同步读取
QString data = FileHandler::readTextFile(":/MCU/DATA/MCU_IO/"+imageName+".txt");
emit requestParsePinData(data);//信号
// ConfigComboBox::parsePinData(data);
qDebug() << "文件内容:" << data;
// emit updateP01(data); // 触发信号
//ui->P01->addItem("New Item");
// ui->P01->addItem("New Item");
// ui->P01->addItem("New Item");
// }
}
ConfigComboBox.h
#ifndef CONFIGCOMBOBOX_H
#define CONFIGCOMBOBOX_H
#include <QComboBox>
#include "ui_mainwindow.h"
#include <QMap>
class ConfigComboBox : public QComboBox
{
Q_OBJECT
public:
explicit ConfigComboBox(QWidget *parent = nullptr, Ui::MainWindow *mainUI = nullptr);
void setcombobox(QString &imagePath);
/
signals:
void requestParsePinData(const QString &data);//信号声明
private slots:
private:
};
#endif // CONFIGCOMBOBOX_H
其实 可以不用ConfigComboBox这个类了,原本我是想脚位的设置放在该类中实现的,但是发现别的类调用ui界面的控件很麻烦,所以把代码又放到mainwindow里面去了,ConfigComboBox里面就处理了以下文件,然后触发信号回到mainwindow,可以不加这个类,我这里先不删除了。
弄完这些后我们实现了选择芯片后,对应的脚位上显示出该脚位可以配置的功能,下面是示例
点击选择芯片,选择完后会出先每个脚位可选功能
效果:
接下来实现的功能是点击对应的功能,弹出配置界面,进行配置。
四.芯片功能配置
实现原理解析
现在我们已经实现了芯片各个引脚功能的选择,现在我们要在选择功能后,跳出一个功能配置界面,比如说我选择了一个普通IO口输出,那我们跳出的的界面里面就要包含IO口可以配置的全部功能供选择,选择完成后我们点击完成配置退出,那我们就完成了该口的配置,同时我们需要实现各种芯片统一的一种格式,方便我们对芯片进行扩展,下面是我定义的一个芯片的配置文件的格式示例,用该模板可以实现不同芯片功能的可扩展性。
我们需要将各种芯片的寄存器配置统一归纳,对各种不同芯片的寄存器名称进行统一命名,这样在配置的时候就不需要针对每个芯片单独的生成一套配置
下面是我写的模板,会根据实际代码生成中的问题会进行优化,
c文件
#include "SC8P052_reg.h" void delay(unsigned int t) { unsigned int i; for(i=0;i<t;i++); } void SYSCLK_init(void)//系统时钟初始化 只有一个时钟源为16Mhz { Oscillator_Control_Register=0x00;//复位 //时钟选择配置 Oscillator_Control_Register|=Oscillator_Control_Register_Frequency_Selection_Div4;//OSCCON=0x50;可选div1 2 4 8 16 32 64 // Oscillator_Control_Register|=Oscillator_Control_Register_Frequency_Selection_32k ; //看门狗配置 Oscillator_Control_Register|=Oscillator_Control_Register_WDT_EN //WDT使能,当配置项里使能时,无效 EN可改为OFF } void IO_init()//端口初始化 { IO_Direction_Register=0x00;//方向寄存器 1输入 0输出 IO_Initial_State_Register=0x00;//初始状态寄存器 IO_Open_Drain_Output_Control=0x00;//开漏输出控制寄存器 1使能 0禁止 IO_Pull_Up_Resistor =0x00;//上拉电阻使能寄存器 1使能 0禁止 IO_Pull_Down_Resistor =0x00;//下拉电阻使能寄存器 1使能 0禁止 IO_Level_Change_Interrupt_Register=0x00;//电平变化中断使能寄存器 1使能 0禁止 } void PWM_init()//PWM初始化 { PWM_Control_Register0=0x00;//复位 PWM_Control_Register0|=PWM_Control_Register0_Clock_Division128;//PWM0时钟分频可选1 2 4 8 16 32 64 128 PWM_Control_Register0|=PWM_Control_Register0_PWM4EN;//PWM4使能 可选使能4 1 0 //PWM_Control_Register0|=PWM_Control_Register0_PWM1EN;//PWM1使能 //PWM_Control_Register0|=PWM_Control_Register0_PWM0EN;//PWM0使能 PWM_Control_Register1=0x00;//初始化 PWM_Control_Register1|=PWM_Control_Register1_Dead_Zone_Enable; //死区使能 PWM_Control_Register1|=PWM_Control_Register1_Dead_Zone_Clock_Division8; //死区时间8分频 可选8 4 2 1 PWM_Control_Register2=0x00;//初始化 PWM_Control_Register2|=PWM_Control_Register2_Pwm4_Output_Invert;//输出取反控制器可选 4 1 0 // PWM_Control_Register2|=PWM_Control_Register2_Pwm1_Output_Invert; // PWM_Control_Register2|=PWM_Control_Register2_Pwm0_Output_Invert; PWM0_1_Period_Low_Register=0x00;//PWM0 1周期寄存器低8位 PWM_4_Period_Low_Register=0x00;//PWM4周期寄存器低8位 PWM_Period_High_Register|=PWM_Period_High_Register_PWMD4_0;//PWM4周期寄存器高两位为0 ,可选0 1 2 3 // PWM_Period_High_Register|=PWM_Period_High_Register_PWMD4_1;//PWM4周期寄存器高两位为1; //PWM_Period_High_Register|=PWM_Period_High_Register_PWMD4_2;//PWM4周期寄存器高两位为2; PWM_Period_High_Register|=PWM_Period_High_Register_PWM4T_0;//PWM4周期寄存器高两位为0 ,可选0 1 2 3 //PWM_Period_High_Register|=PWM_Period_High_Register_PWM4T_1;//PWM4周期寄存器高两位为1; //PWM_Period_High_Register|=PWM_Period_High_Register_PWM4T_2;//PWM4周期寄存器高两位为2; PWM_Period_High_Register|= PWM_Period_High_Register_PWMT0and1_0;//pwm0和1周期高二位 为0 可选0 1 2 3 //PWM_Period_High_Register|= PWM_Period_High_Register_PWMT0and1_1;//pwm0和1周期高二位 为1 可选0 1 2 3 //PWM_Period_High_Register|= PWM_Period_High_Register_PWMT0and1_2;//pwm0和1周期高二位 为2 可选0 1 2 3 PWM0_Duty_Cycle_Low_Register=0x00;//PWM0 占空比寄存器低8位 PWM1_Duty_Cycle_Low_Register=0x00;//PWM1 占空比寄存器低8位 PWM4_Duty_Cycle_Low_Register=0x00;//PWM4 占空比寄存器低8位 PWM0_1_Duty_Cycle_High_Register|=PWM0_1_Duty_Cycle_High_Register_PWM1_0;//PWM1 占空比高位寄存器 0 可选0 1 2 3 //PWM0_1_Duty_Cycle_High_Register|=PWM0_1_Duty_Cycle_High_Register_PWM1_0;//PWM1 占空比高位寄存器 1 可选0 1 2 3 PWM0_1_Duty_Cycle_High_Register|=PWM0_1_Duty_Cycle_High_Register_PWM0_0 ;//PWM0 占空比高位寄存器 0 可选0 1 2 3 //PWM0_1_Duty_Cycle_High_Register|=PWM0_1_Duty_Cycle_High_Register_PWM0_1 ;//PWM0 占空比高位寄存器 1 可选0 1 2 3 PWM0_1_Dead_PWMtime_register =0x00;//PWM0 和 PWM1 死区时间寄存器 有效位为0-5bit } void CMP_init()//比较器初始化 { Comparator_Control_Register0=0x00;//复位 Comparator_Control_Register0|=Comparator_Control_Register0_CMPEN ;//使能比较器 } void TIMER_init()//定时器初始化 { Timer2_Data_Register=0x00;//数据寄存器 Timer2_Period_Register=0x00;//周期寄存器 Timer2_Control_Register|=Timer2_Control_Register_Postscaler1;//TIMER2 输出后分频比选择位不分 可选分频 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Timer2_Control_Register|=Timer2_Control_Register_En;//时钟使能 Timer2_Control_Register|=Timer2_Control_Register_Div1;//TIMER2 前分频 可选1 ,4 ,16 } void INT_init()//中断初始化 { Interrupt_Control_Register=0x00;//中断控制寄存器 //Interrupt_Control_Register|=Interrupt_Control_Register_Global_Interrupt_Enable;//全局中断使能位 // Interrupt_Control_Register|=Interrupt_Control_Register_Peripheral_Interrupt_Enable;//外设中断使能位 // Interrupt_Control_Register|=Interrupt_Control_Register_External_Interrupt_Enable;//外部中断使能位 //Interrupt_Control_Register|=Interrupt_Control_Register_Level_Change_Interrupt_Enable;//电平变化中断使能位 Peripheral_Interrupt_Enable_Register=0x00;//外设中断使能寄存器 // Peripheral_Interrupt_Enable_Register|=Peripheral_Interrupt_Enable_Register_CMPIE;//比较器中断使能位 // Peripheral_Interrupt_Enable_Register|=Peripheral_Interrupt_Enable_Register_PWMIE;//PWM中断使能位 // Peripheral_Interrupt_Enable_Register|=Peripheral_Interrupt_Enable_Register_TMR2IE;//定时器2中断使能位 }
.h文件
#ifndef __SC8P052_REG_H__ #define __SC8P052_REG_H__ #include<sc.h>//包含MCU的寄存器的头文件 /*--------------IO口配置寄存器SC8P052----------------*/ /*--------------系统频率--------------------------------*/ //#define Fsys 4000000//系统频率,由IRCF分高频,或低频产生,默认不配置为/4 #define F_high 16000000//系统高频时钟频 #define F_low 32000//系统低频时钟频 //系统可配置为双时钟模式 //内部只有一个时钟源为16000000 /*-------------------位掩码------------------------------*/ #define bitmask_1 0x01//或上该掩码可以把该位置1,与上反码可以置0 #define bitmask_2 0x02// #define bitmask_3 0x04 #define bitmask_4 0x08 #define bitmask_5 0x10 #define bitmask_6 0x20 #define bitmask_7 0x40 #define bitmask_8 0x80 /*---------------SC8P052IO口只有六个分别为RB0-RB5---------------*/ #define IO_Direction_Register TRISB //方向寄存器 #define IO_Initial_State_Register PORTB//io初始状态寄存器 #define IO_Direction_Register_In 1 //方向寄存器设置输入 #define IO_Direction_Register_Out 0 //方向寄存器设置输出 #define IO_Open_Drain_Output_Control ODCONB//开漏输出设置 #define IO_Open_Drain_Output_Control_On 1 //开漏使能!!RB3固定开漏 #define IO_Open_Drain_Output_Control_Off 0//开漏失能 #define IO_Pull_Up_Resistor WPUB//IO上拉电阻 #define IO_Pull_Down_Resistor WPDB//IO下拉电阻 #define IO_Pull_Up_Resistor_En 1//IO上拉使能 #define IO_Pull_Up_Resistor_Off 0//IO上拉失能 #define IO_Pull_Down_Resistor_En 1//IO下拉使能 #define IO_Pull_Down_Resistor_Off 0//IO下拉失能 #define IO_Level_Change_Interrupt_Register IOCB//IO口电平变化中断控制位 #define IO_Level_Change_Interrupt_Register_On 1//电平翻转中断使能 #define IO_Level_Change_Interrupt_Register_Off 0//电平翻转中断失能 /*---------------中断配置寄存器--------------------*/ #define Interrupt_Control_Register INTCON//中断控制寄存器 #define Interrupt_Control_Register_Global_Interrupt_Enable 0x80//总中断使能 #define Interrupt_Control_Register_Peripheral_Interrupt_Enable 0x40//外设中断使能 #define Interrupt_Control_Register_External_Interrupt_Enable 0x10//外部中断使能 #define Interrupt_Control_Register_Level_Change_Interrupt_Enable 0x08//RB电平变化中断使能 #define Global_Interrupt_Enable_Bit GIE//总中断允许位 #define Peripheral_Interrupt_Enable_Bit PEIE//外设中断允许位 #define External_Interrupt_Enable_Bit INTE//外部中断允许位 #define Level_Change_Interrupt_Enable_Bit RBIE//电平变化中断允许位 #define External_Interrupt_Flag_Bit INTF// INT外部中断标志位 #define PORTB_Level_Change_Interrupt_Flag_Bit RBIF//PORTB电平变化中断标志位 #define Peripheral_Interrupt_Enable_Register PIE1//外设中断允许寄存器 #define Peripheral_Interrupt_Enable_Register_CMPIE 0x20//比较器中断允许位 #define Peripheral_Interrupt_Enable_Register_PWMIE 0x10//PWM中断允许位(PWM0/1) #define Peripheral_Interrupt_Enable_Register_TMR2IE 0x02//TIMER2与PR2匹配中断允许位 #define Comparator_Interrupt_Enable_Bit CMPIE: //比较器中断允许位 #define PWM_Interrupt_Enable_Bit_0_1 PWMIE: //PWM中断允许位(PWM0/1) #define TIMER2_Data_and_Period_Match_Interrupt_Enable_Bit TMR2IE: //TIMER2与PR2匹配中断允许位 /*------------定时器配置寄存器-------------------------*/ /*------------TIMER2 后分频器的输出用于使 PIR1 寄存器的 TMR2IF 中断标志位置 1*/ #define Timer2_Data_Register TMR2//定时器2数据寄存器 #define Timer2_Period_Register PR2 //周期寄存器 #define Timer2_Control_Register T2CON //控制寄存器 ,寄存器的值没赋值为0 #define Timer2_Control_Register_Postscaler1 0x00 // TIMER2 输出后分频比选择位 对Timer2_Control_Registe操作时或上这个值 #define Timer2_Control_Register_Postscaler2 0x08 // TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_Postscaler3 0x18 // TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_Postscaler4 0x20// TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_Postscaler5 0x28// TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_Postscaler6 0x14// TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_Postscaler7 0x18// TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_Postscaler8 0x20// TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_Postscaler9 0x28// TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_Postscaler10 0x30// TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_Postscaler11 0x38// TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_Postscaler12 0x40// TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_Postscaler13 0x48// TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_Postscaler14 0x50// TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_Postscaler15 0x58// TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_Postscaler16 0x60// TIMER2 输出后分频比选择位 操作时或上这个值 #define Timer2_Control_Register_En 0x04//TIMER2使能 对Timer2_Control_Registe 或上这个 #define Timer2_Control_Register_Div1 0x00 //1分频 #define Timer2_Control_Register_Div4 0x01//4分频 #define Timer2_Control_Register_Div16 0x02//16分频 /* //下面是伪代码表示芯片运行的逻辑 周期= 1/(Fsys/4/X)过一个周期后 Timer2_Data_Register++(X=1,4,16) if(Timer2_Period_Register==Timer2_Data_Register) { Timer2_Data_Register=0; if (Timer2_Control_Registe_Cnt13) { int i=0; i++; if(i==13)TMR2IF =1;//中断标志位置1 } } //TMR2 和 PR2 寄存器均可读写。任何复位时,TMR2 寄存器均被设置为 00h 且 PR2 寄存器被设置为 FFh,发生复位时要重新设置!! Timer2_Control_Registe==1 or 复位-> DivX=0 and Postscalerx=0 复位后重新设置值!! 写Timer2_Control_Registe 不会将Timer2_Data_Register 清零,在 Timer2_Control_Registe_En=0 时,TMR2 寄存器不能进行写操作 */ /*------------------PWM配置寄存器-----------------------------*/ #define PWM_Control_Register0 PWMCON0 //PWM 控制寄存器0 #define PWM_Control_Register0_Clock_Division128 0xe0 //PWM时钟分频 对上面代码操作时或上这个值 #define PWM_Control_Register0_Clock_Division64 0xc0 //PWM时钟分频 #define PWM_Control_Register0_Clock_Division32 0xa0 //PWM时钟分频 #define PWM_Control_Register0_Clock_Division16 0x80 //PWM时钟分频 #define PWM_Control_Register0_Clock_Division8 0x60 //PWM时钟分频 #define PWM_Control_Register0_Clock_Division4 0x40 //PWM时钟分频 #define PWM_Control_Register0_Clock_Division2 0x20 //PWM时钟分频 #define PWM_Control_Register0_Clock_Division1 0xe0 //PWM时钟分频 #define PWM_Control_Register0_PWM4EN 0x10//使能PWM4 #define PWM_Control_Register0_PWM1EN 0x02//使能PWM1 #define PWM_Control_Register0_PWM0EN 0x01//使能PWM0 #define PWM_Control_Register1 PWMCON1 //PWM 控制寄存器1 #define PWM_Control_Register1_Dead_Zone_Enable 0x10// PWM0死区使能 #define PWM_Control_Register1_Dead_Zone_Clock_Division8 0x03//死区时钟源分频 #define PWM_Control_Register1_Dead_Zone_Clock_Division4 0x02//死区时钟源分频 #define PWM_Control_Register1_Dead_Zone_Clock_Division2 0x01//死区时钟源分频 #define PWM_Control_Register1_Dead_Zone_Clock_Division1 0x00//死区时钟源分频 #define PWM_Control_Register2 PWMCON2 //PWM 控制寄存器2 #define PWM_Control_Register2_Pwm4_Output_Invert 0x10//输出取反控制位 #define PWM_Control_Register2_Pwm1_Output_Invert 0x02//输出取反控制位 #define PWM_Control_Register2_Pwm0_Output_Invert 0x01//输出取反控制位 #define PWM0_1_Period_Low_Register PWMTL//PWM0_1周期低位寄存器 #define PWM_4_Period_Low_Register PWMT4L//PWM4周期低位寄存器 #define PWM_Period_High_Register PWMTH//周期高位寄存器 #define PWM_Period_High_Register_PWMD4_0 0x00//pwm4占空比高二位 #define PWM_Period_High_Register_PWMD4_1 0x10//pwm4占空比高二位 #define PWM_Period_High_Register_PWMD4_2 0x20//pwm4占空比高二位 #define PWM_Period_High_Register_PWMD4_3 0x30//pwm4占空比高二位 #define PWM_Period_High_Register_PWM4T_0 0x00//pwm4周期高二位 #define PWM_Period_High_Register_PWM4T_1 0x04//pwm4周期高二位 #define PWM_Period_High_Register_PWM4T_2 0x08//pwm4周期高二位 #define PWM_Period_High_Register_PWM4T_3 0x0c//pwm4周期高二位 #define PWM_Period_High_Register_PWMT0and1_0 0x00//pwm0和1周期高二位 #define PWM_Period_High_Register_PWMT0and1_1 0x01//pwm0和1周期高二位 #define PWM_Period_High_Register_PWMT0and1_2 0x02//pwm0和1周期高二位 #define PWM_Period_High_Register_PWMT0and1_3 0x03//pwm0和1周期高二位 #define PWM0_Duty_Cycle_Low_Register PWMD0L//PWM0 占空比低位寄存器 #define PWM1_Duty_Cycle_Low_Register PWMD1L //PWM1 占空比低位寄存器(1AH) #define PWM4_Duty_Cycle_Low_Register PWMD4L //PWM4 占空比低位寄存器 #define PWM0_1_Duty_Cycle_High_Register PWMD01H//PWM0 和 PWM1 占空比高位寄存器 (1EH) #define PWM0_1_Duty_Cycle_High_Register_PWM1_0 0x00//PWM1 占空比高位寄存器 0 #define PWM0_1_Duty_Cycle_High_Register_PWM1_1 0x10//PWM1 占空比高位寄存器 1 #define PWM0_1_Duty_Cycle_High_Register_PWM1_2 0x20//PWM1 占空比高位寄存器 2 #define PWM0_1_Duty_Cycle_High_Register_PWM1_3 0x30 //PWM1 占空比高位寄存器 3 #define PWM0_1_Duty_Cycle_High_Register_PWM0_0 0x00//PWM0 占空比高位寄存器 0 #define PWM0_1_Duty_Cycle_High_Register_PWM0_1 0x01//PWM0 占空比高位寄存器 1 #define PWM0_1_Duty_Cycle_High_Register_PWM0_2 0x02//PWM0 占空比高位寄存器 2 #define PWM0_1_Duty_Cycle_High_Register_PWM0_3 0x03//PWM0 占空比高位寄存器 3 #define PWM0_1_Dead_PWMtime_register PWM01DT//PWM0 和 PWM1 死区时间寄存器 有效位为0-5bit /*---------------------比较器寄存器------------------------------ */ #define Comparator_Control_Register0 CMPCON0//比较器控制寄存器0 #define Comparator_Control_Register0_CMPEN 0x80 //使能比较器 #define Comparator_Control_Register0_P_CMP+ 0x40//正极选择CMP+端口电压 #define Comparator_Control_Register0_P_VDD_DIV 0x00//正极选择VDD分压 #define Comparator_Control_Register0_N_CMP0- 0x00 //负端选择CMP0-端口 #define Comparator_Control_Register0_N_CMP1- 0x08 //负端选择CMP1-端口 #define Comparator_Control_Register0_N_CMP2- 0x10//负端选择CMP2-端口 #define Comparator_Control_Register0_N_CMP3- 0x18//负端选择CMP3-端口 #define Comparator_Control_Register0_N_VDD_DIV 0x20//负端选择VDD分压 #define Comparator_Control_Register0_N_BG 0x28 //负端选择BG1.2V #define Comparator_Control_Register0_OUT_Flip 0x04//OUT端口取反 #define Comparator_Control_Register0_CMPO_EN 0x01 //CMPO端口输出使能 //#define Comparator_Control_Register0_CMPOUT_CMP 0x40 //比较器输出 #define Comparator_Control_Register1 CMPCON1 //比较器控制寄存器1 #define Comparator_Control_Register1_INT_UP 0x80//CMP中断上升沿触发 #define Comparator_Control_Register1_INT_DOWN 0x00 #define Comparator_Control_Register1_AN_EN 0x40 //CMP模拟口使能 #define Comparator_Control_Register1_VDD_DIV_9_32 0x00//1/4+1/32 #define Comparator_Control_Register1_VDD_DIV_10_32 0x01 #define Comparator_Control_Register1_VDD_DIV_11_32 0x02 #define Comparator_Control_Register1_VDD_DIV_12_32 0x03 #define Comparator_Control_Register1_VDD_DIV_13_32 0x04 #define Comparator_Control_Register1_VDD_DIV_14_32 0x05 #define Comparator_Control_Register1_VDD_DIV_15_32 0x06 #define Comparator_Control_Register1_VDD_DIV_16_32 0x07 #define Comparator_Control_Register1_VDD_DIV_17_32 0x08 #define Comparator_Control_Register1_VDD_DIV_18_32 0x09 #define Comparator_Control_Register1_VDD_DIV_19_32 0x0A #define Comparator_Control_Register1_VDD_DIV_20_32 0x0B #define Comparator_Control_Register1_VDD_DIV_21_32 0x0C #define Comparator_Control_Register1_VDD_DIV_22_32 0x0D #define Comparator_Control_Register1_VDD_DIV_23_32 0x0E #define Comparator_Control_Register1_VDD_DIV_24_32 0x0F #define Comparator_Control_Register1_VDD_DIV_1_24 0x10 #define Comparator_Control_Register1_VDD_DIV_2_24 0x11 #define Comparator_Control_Register1_VDD_DIV_3_24 0x12 #define Comparator_Control_Register1_VDD_DIV_4_24 0x13 #define Comparator_Control_Register1_VDD_DIV_5_24 0x14 #define Comparator_Control_Register1_VDD_DIV_6_24 0x15 #define Comparator_Control_Register1_VDD_DIV_7_24 0x16 #define Comparator_Control_Register1_VDD_DIV_8_24 0x17 #define Comparator_Control_Register1_VDD_DIV_9_24 0x18 #define Comparator_Control_Register1_VDD_DIV_10_24 0x19 #define Comparator_Control_Register1_VDD_DIV_11_24 0x1A #define Comparator_Control_Register1_VDD_DIV_12_24 0x1B #define Comparator_Control_Register1_VDD_DIV_13_24 0x1C #define Comparator_Control_Register1_VDD_DIV_14_24 0x1D #define Comparator_Control_Register1_VDD_DIV_15_24 0x1E #define Comparator_Control_Register1_VDD_DIV_16_24 0x1F #define Comparator_Control_Register1_VDD_DIV_9_40 0x20 #define Comparator_Control_Register1_VDD_DIV_10_40 0x21 #define Comparator_Control_Register1_VDD_DIV_11_40 0x22 #define Comparator_Control_Register1_VDD_DIV_12_40 0x23 #define Comparator_Control_Register1_VDD_DIV_13_40 0x24 #define Comparator_Control_Register1_VDD_DIV_14_40 0x25 #define Comparator_Control_Register1_VDD_DIV_15_40 0x26 #define Comparator_Control_Register1_VDD_DIV_16_40 0x27 #define Comparator_Control_Register1_VDD_DIV_17_40 0x28 #define Comparator_Control_Register1_VDD_DIV_18_40 0x29 #define Comparator_Control_Register1_VDD_DIV_19_40 0x2A #define Comparator_Control_Register1_VDD_DIV_20_40 0x2B #define Comparator_Control_Register1_VDD_DIV_21_40 0x2C #define Comparator_Control_Register1_VDD_DIV_22_40 0x2D #define Comparator_Control_Register1_VDD_DIV_23_40 0x2E #define Comparator_Control_Register1_VDD_DIV_24_40 0x2F #define Comparator_Control_Register1_VDD_DIV_1_32 0x30 #define Comparator_Control_Register1_VDD_DIV_2_32 0x31 #define Comparator_Control_Register1_VDD_DIV_3_32 0x32 #define Comparator_Control_Register1_VDD_DIV_4_32 0x33 #define Comparator_Control_Register1_VDD_DIV_5_32 0x34 #define Comparator_Control_Register1_VDD_DIV_6_32 0x35 #define Comparator_Control_Register1_VDD_DIV_7_32 0x36 #define Comparator_Control_Register1_VDD_DIV_8_32 0x37 #define Comparator_Control_Register1_VDD_4V8 0x15 #define Comparator_Control_Register1_VDD_4V36 0x22 #define Comparator_Control_Register1_VDD_4V27 0x00 #define Comparator_Control_Register1_VDD_4V11 0x16 #define Comparator_Control_Register1_VDD_3V84 0x01 #define Comparator_Control_Register1_VDD_3V69 0x24 #define Comparator_Control_Register1_VDD_3V60 0x17 #define Comparator_Control_Register1_VDD_3V49 0x02 #define Comparator_Control_Register1_VDD_3V43 0x25 #define Comparator_Control_Register1_VDD_3V20 0x03 #define Comparator_Control_Register1_VDD_2V95 0x04 #define Comparator_Control_Register1_VDD_2V88 0x19 #define Comparator_Control_Register1_VDD_2V82 0x28 #define Comparator_Control_Register1_VDD_2V74 0x05 #define Comparator_Control_Register1_VDD_2V67 0x29 #define Comparator_Control_Register1_VDD_2V62 0x1A #define Comparator_Control_Register1_VDD_2V56 0x06 #define Comparator_Control_Register1_VDD_2V53 0x2A #define Comparator_Control_Register1_VDD_2V40 0x07 #define Comparator_Control_Register1_VDD_2V29 0x2C #define Comparator_Control_Register1_VDD_2V26 0x08 #define Comparator_Control_Register1_VDD_2V18 0x2D #define Comparator_Control_Register1_VDD_2V13 0x09 #define Comparator_Control_Register1_VDD_2V09 0x2E #define Comparator_Control_Register1_VDD_2V06 0x1D #define Comparator_Control_Register1_VDD_2V02 0x0A #define Comparator_Control_Register1_VDD_2V00 0x2F /*---------------------其他寄存器定义---------------------------*/ #define Prescaler_Control_Register OPTION_REG// 预分频寄存器 #define Prescaler_Control_Register_INTEDG 1 //触发方式选择位上升沿 #define Prescaler_Control_Register_INTEDG 0 //触发方式选择位上升沿 #define Prescaler_Control_Register_Div1 0x00 //1分频 #define Prescaler_Control_Register_Div2 0x01 //2分频 #define Prescaler_Control_Register_Div4 0x02 //4分频 #define Prescaler_Control_Register_Div8 0x03 //8分频 #define Prescaler_Control_Register_Div16 0x04 //16分频 #define Prescaler_Control_Register_Div32 0x05 //32分频 #define Prescaler_Control_Register_Div64 0x06 //64分频 #define Prescaler_Control_Register_Div128 0x07 //128分频 #define Oscillator_Control_Register OSCCON //振荡器控制寄存器 #define Oscillator_Control_Register_Frequency_Selection_Div1 0x70 //1分频(IRCF) #define Oscillator_Control_Register_Frequency_Selection_Div2 0x60 //2分频 #define Oscillator_Control_Register_Frequency_Selection_Div4 0x50 //4分频默认值 #define Oscillator_Control_Register_Frequency_Selection_Div8 0x40 //8分频 #define Oscillator_Control_Register_Frequency_Selection_Div16 0x30 //16分频 #define Oscillator_Control_Register_Frequency_Selection_Div32 0x20 //32分频 #define Oscillator_Control_Register_Frequency_Selection_Div64 0x10 //64分频 #define Oscillator_Control_Register_Frequency_Selection_32k 0x00 //32k晶振(LFINTOSC) #define Oscillator_Control_Register_WDT_EN 0x02 //WDT使能,当配置项里使能时,无效 #define Oscillator_Control_Register_WDT_Off 0x00 //WDT失能,当配置项里使能时,无效 #define WDT_Overtime_Flag TO//WDT溢出标志位0为溢出 #define Stop_flag PD//0为执行了STOP指令 #define Comparator_Interrupt_Flag CMPIF//比较器中断标志位(必须由软件清零) #define Pwm_Interrupt_Flag PWMIF//PWM中断标志位(必须由软件清零) #define TIMER2_Data_and_Period_Int_flag TMR2IF// TIMER2与PR2匹配中断标志位(必须由软件清零) //--------以上是寄存器各种模式的定义---------------- //---------接下来配置寄存器函数----------------------- void SYSCLK_init(void); void IO_init(void); void PWM_init(void); void CMP_init(void); void TIMER_init(void); void INT_init(void); void delay(unsigned int t); #endif
接下来是点击图片中的配置界面后,由于各种芯片的不同,想要实现统一很困难,所以我的想法是点击对应脚位的功能后,跳出相应的模板代码,再根据写代码的人的平时习惯,跳出相应的代码模板,代码模板可以根据不同的人,设置相应不同的模板代码,跳出模板代码后可以进行编辑,编辑完成后保存。当所有的配置结束后再把代码统一导出。
持续更新中————————