(*((void (*)(void))(*(unsigned long *)0x2c)))(); 是什么意思?

本文深入解析了在8962的boot_demo1中出现的一条复杂C语言指令(((void()(void))(*(unsignedlong*)0x2c)))();。文章详细解释了这条指令如何将Flash地址0x2C中的内容转化为函数指针并执行,揭示了其在程序引导过程中的作用。

(((void ()(void))((unsigned long )0x2c)))(); 是什么意思?
在8962的boot_demo1中 (
((void (
)(void))(*(unsigned long *)0x2c)))(); 是什么意思?是把程序引导到地址为0X2C的位置?

这个语句会执行位于bootloader的SVC(软中断)异常服务例程,还是分解一下吧:

(*(unsigned long *)0x2c):将0x2C强制转化为unsigned long类型指针,并指向该地址所在的数据;

void (*)(void) :函数指针,指针名为空,该函数参数为空,返回值为空

(void ()(void))((unsigned long *)0x2c):将Flash地址0x2C中的内容强制转化为函数指针,该函数参数为空,返回值为空

(((void ()(void))(*(unsigned long *)0x2c)))();:调用函数,即开始从启动代码中的UpdateHandler标号处开始执行

class MainWindow : public QObject,public QMainWindow { Q_OBJECT; public: MainWindow(QWidget* parent = nullptr); ~MainWindow(); void loadjson(); void ranking(); void setCheckboxState(QTreeWidget* treeWidget, const QString& parentText, const QString& itemText, bool checked); HANDLE getProcessHandleByNmae(const std::string& processName); //获取模拟器进程句柄 static LRESULT CALLBACK WheelHookProc(int nCode, WPARAM wParam, LPARAM lParam); //鼠标滚轮钩子 //unsigned long long readshiye(); void readquanju(); unsigned long long readbiansu(); unsigned long long readnianhe(); //unsigned long long readtuqiu(); unsigned long long readyaoganjiexian(); void readfsjiexian(); unsigned long long readyaoganhuitan(); unsigned long long readncdx(); unsigned long long readyaogan10000(); unsigned long long readdldjd(); unsigned long long readygyc(); //void readygdx(); //void readygtm(); //void readheiping1(); //void readheiping2(); //void readdanliandianjd(); unsigned long long readjuneiqupi(); //void readduiyouzuobiao(); //void readshanghao(); //void readtuanzhanduiyouzb(); //void readtaoshaduiyouzb1(); //void readtaoshaduiyouzb2(); void readshiye(); void readjtygX(); void readjtygY(); //void writequanju(); void writeshiye(); //void writequanju(); void writebiansu(); void writenianhe(); void writetuqiu(); void writeyaoganjiexian(); void writefsjiexian(); void writeyaoganhuitan(); void writencdx(); void writeyaogan10000(); void writeygyc(); //void writeygtm(); //void writeheiping1(); //void writeheiping2(); //void writedanliandianjd(); void writejuneiqupi(); //void writeduiyouzuobiao(); //void writeshanghao(); //void writetuanzhanduiyouzb(); //void writetaoshaduiyouzb1(); //void writetaoshaduiyouzb2(); void writePos(float x, float y); public slots: void treewidget_itemClicked(); //点击不同的items,索引stackedwidget void init(); //点击初始化按钮做的工作 std::string choosemnq(); //选择模拟器 void bypass(); //std::vector<DWORD_PTR> Search(HANDLE hProcess, const unsigned char* pattern, const char* mask, DWORD_PTR startAddr, DWORD_PTR endAddr); public: //特征码 std::vector<BYTE> quanjuAob = { 0xD8, 0x00, 0x00, 0x00, 0x63, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; std::vector<BYTE> biansuAob = {0x00, 0x00, 0x80, 0x3F, 0xAB, 0xAA, 0xAA, 0x3E, 0x8F, 0xC2, 0xF5}; std::vector<BYTE> nianheAob = { 0x01 ,0x00 ,0x00, 0x00, 0x00, 0x00, 0x00 ,0x00, 0xA6, 0x00 ,0x00, 0x00, 0x00, 0x00, 0x01 ,0x00 ,0x1F, 0x01, 0x00 ,0x00 ,0x00 ,0x00 ,0x00, 0x00 }; std::vector<BYTE> tuqiuAob = {0xA6, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x7B, 0x02, 0x02, 0x00, 0x38, 0x04, 0x03, 0x00, 0x30, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2F, 0x01, 0x02, 0x00, 0x05 }; std::vector<BYTE> yaoganyanchiAob = {0x0A, 0xD7, 0xA3, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x42}; std::vector<BYTE> fsjiexianAob = { 0xE7,0x00,0x04,0x00,0x10,0x04,0x00,0x00,0x0C,0x00,0x04,0x00,0x8F,0xC2,0xF5,0x3D }; std::vector<BYTE> yaoganjiexianAob = { 0x2C, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x05, 0x00, 0x0A, 0xD7, 0x23, 0x3C }; std::vector<BYTE> yaoganhuitanAob = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40}; std::vector<BYTE> ncdxAob = { 0x22, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x29, 0x01 }; std::vector<BYTE> yaogan10000Aob = {0x88, 0x56, 0x64, 0x20, 0xAF, 0xD5, 0x08}; //摇杆10000 std::vector<BYTE> ygtmAob = {0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFD, 0x45}; //摇杆透明 std::vector<BYTE> heipingAob1 = {0x00, 0x80, 0x3B, 0xC4}; //黑屏1 std::vector<BYTE> heipingAob2 = {0x00, 0x00, 0x48, 0x44}; //黑屏2 std::vector<BYTE> danliandianjdAob = {0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0C}; std::vector<BYTE> juneiqupiAob = { 0x80, 0x3F, 0x8F, 0x02, 0x03, 0x00 }; //局内去皮 std::vector<BYTE> duiyouzuobiaoAob = {0x50, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x41, 0x00, 0x00, 0x00, 0x3F}; //队友坐标aob std::vector<BYTE> shanghaoAob = {0x00, 0x00, 0x40, 0x8A, 0xF7, 0x01, 0x00, 0x00, 0x00, 0x00}; //上号 std::vector<BYTE> tuanzhanduiyouzb = {0xC3, 0xF5, 0xA8, 0x3E, 0x01, 0x00, 0x00, 0x00, 0x00}; //团战队友坐标 std::vector<BYTE> taoshaduiyouzb1 = {0xC3, 0xF5, 0xA8, 0x3E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; //逃杀队友坐标1 std::vector<BYTE> taoshaduiyouzb2 = {0xFF, 0xFF}; //逃杀队友坐标2 std::vector<BYTE> ygycAob = { 0x01,0x01,0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x80, 0x3F, 0x0D ,0xE0,0x4D,0x3F }; //摇杆延迟 std::vector<BYTE> ygdxAob = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x42, 0x00, 0x00, 0x00, 0x00 }; //摇杆大小 static HANDLE hProcess; static std::string mnq; static unsigned long long nianheAdress; static unsigned long long ncdxAdress; static unsigned long long biansuAdress; static unsigned long long ygycAdress; static unsigned long long yaoganhuitanAdress; static unsigned long long ygrongchaAdress; static unsigned long long yaogan10000Adress; static unsigned long long yaoganjiexianAdress; static unsigned long long fsjiexianAdress_1; static unsigned long long fsjiexianAdress_2; static unsigned long long fsjiexianAdress_3; static unsigned long long juneiqupiAdress; //通过全局特征码找到的地址 static unsigned long long shiyeAdress; static unsigned long long tuqiuAdress; static unsigned long long ncygAdress; static unsigned long long tijiAdress; static unsigned long long zhanjuzhiAdress; static unsigned long long ncygjsxAdress; static unsigned long long ncygjsyAdress; static unsigned long long xmin; static unsigned long long xmax; static unsigned long long ymin; static unsigned long long ymax; static unsigned long long selfsize; // static bool tuqiuFlag; static bool yaoganjiexianFlag; static bool yaoganhuitanFlag; static bool gunlunshiyeFlag; static bool fsjiexianFlag; static bool juneiqupiFlag; static bool yaoganyouhuaFlag; static float step; //-------------------------------------合球相关变量,函数---------------------------------------->> static UINT sanjiaojian1, sanjiaojian2, sanjiaojian3, chongqiujian, sifenjian, zhongfenjian, xuanzhuanjian1, banxuanjian1, xuanzhuanjian2, banxuanjian2, sheshoujian, houyangjian, tuqiujian, fenshenjian; static bool sanjiao1Flog, sanjiao2Flog, sanjiao3Flog, chongqiuFlog, sifenFlog, zhongfenFlog, xuanzhuan1Flog, banxuan1Flog, xuanzhuan2Flog, banxuan2Flog, sheshouFlog, houyangFlog; static bool autosanjiao_1_Flog, autosanjiao_2_Flog, autosanjiao_3_Flog,autosifenFlog,autozhongfenFlog,autohouyangFlog; static float sj1jd, sj2jd, sj3jd, sj1hqfd, sj1zyfd; static bool sj1jiantouFlog, sj1tqFlog; static float jtygX, jtygY,dx,dy,sx1,sy1,sx2,sy2 ,shiye; POINT cursorPos_1; //落点坐标 POINT cursorPos_2; //松开鼠标坐标 POINT mousePos; //合球时鼠标位置 POINT centerPos; //中心点坐标 POINT point1; //到第一个点坐标 POINT point2; //到第二个点坐标 POINT point3; //到第三个点坐标 HWND hWnd; RECT rect; HWND getRectHwnd(); //获取窗口句柄 void getRectCenter(); UINT virtualkey(QString key); void SendScanKey(BYTE vkCode); void KeyDown(BYTE vkCode); void KeyUp(BYTE vkCode); void sanjiao1(); public: Ui::MainWindow ui; QThreadPool* threadPool; AndroidTool tool; // Android工具实例 static HHOOK WheelHookID; //滚轮hook句柄 static MainWindow* instance; // 静态实例指针 static SearchTask* searchTask; //搜索任务 };这是我的类
08-31
libsvm报错 make 错误使用 mex svm.obj:svm.cpp:(.text+0x10de): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x1114): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x11fb): undefined reference to `__cxa_throw_bad_array_new_length' svm.obj:svm.cpp:(.text+0x1225): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x18f1): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x190b): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x1929): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x1964): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x19e7): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x1a09): more undefined references to `operator new[](unsigned long long)' follow svm.obj:svm.cpp:(.text+0x2161): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x216f): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x217d): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x218b): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2199): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x21a7): more undefined references to `operator delete[](void*)' follow svm.obj:svm.cpp:(.text+0x21f0): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2200): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x220c): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x224d): undefined reference to `__cxa_throw_bad_array_new_length' svm.obj:svm.cpp:(.text+0x22e7): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x22f3): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x23f8): undefined reference to `operator new(unsigned long long)' svm.obj:svm.cpp:(.text+0x243d): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x24fe): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text+0x250f): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2520): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2528): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x258b): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2596): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x25a2): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2667): undefined reference to `operator new(unsigned long long)' svm.obj:svm.cpp:(.text+0x26b9): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x26d1): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2700): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x27d3): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2802): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x287f): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text+0x2890): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x28a1): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x28b2): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x28c3): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x28d4): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2919): more undefined references to `operator delete[](void*)' follow svm.obj:svm.cpp:(.text+0x2961): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x296c): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2978): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2a63): undefined reference to `operator new(unsigned long long)' svm.obj:svm.cpp:(.text+0x2ab5): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2acd): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2afc): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2bd3): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2c02): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2c86): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text+0x2c97): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2ca8): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2cb9): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2cca): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2cdb): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2d39): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2dfb): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2e64): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2e83): undefined reference to `operator new(unsigned long long)' svm.obj:svm.cpp:(.text+0x2ec8): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2f82): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2fa3): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text+0x2fb4): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x3036): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x303f): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x3067): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x3073): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x3118): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x3138): undefined reference to `operator new(unsigned long long)' svm.obj:svm.cpp:(.text+0x3182): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x3239): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x325a): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text+0x326b): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x32af): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x32b7): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x32d3): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x32e1): undefined reference to `__cxa_throw_bad_array_new_length' svm.obj:svm.cpp:(.text+0x32f9): undefined reference to `__cxa_throw_bad_array_new_length' svm.obj:svm.cpp:(.text+0x3300): undefined reference to `__cxa_throw_bad_array_new_length' svm.obj:svm.cpp:(.text+0x332e): undefined reference to `__cxa_throw_bad_array_new_length' svm.obj:svm.cpp:(.text+0x3333): undefined reference to `__cxa_throw_bad_array_new_length' svm.obj:svm.cpp:(.text+0x3338): more undefined references to `__cxa_throw_bad_array_new_length' follow svm.obj:svm.cpp:(.text+0x1239): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x1275): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.xdata+0x1dc): undefined reference to `__gxx_personality_seh0' svm.obj:svm.cpp:(.text$_ZN6SolverD0Ev[_ZN6SolverD0Ev]+0x6): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN9Solver_NUD0Ev[_ZN9Solver_NUD0Ev]+0x6): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN5SVC_QD1Ev[_ZN5SVC_QD1Ev]+0x21): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVC_QD1Ev[_ZN5SVC_QD1Ev]+0x3f): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN5SVC_QD1Ev[_ZN5SVC_QD1Ev]+0x4d): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN11ONE_CLASS_QD1Ev[_ZN11ONE_CLASS_QD1Ev]+0x31): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN11ONE_CLASS_QD1Ev[_ZN11ONE_CLASS_QD1Ev]+0x3f): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD1Ev[_ZN5SVR_QD1Ev]+0x31): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD1Ev[_ZN5SVR_QD1Ev]+0x3f): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD1Ev[_ZN5SVR_QD1Ev]+0x4d): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD1Ev[_ZN5SVR_QD1Ev]+0x5b): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD1Ev[_ZN5SVR_QD1Ev]+0x69): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD1Ev[_ZN5SVR_QD1Ev]+0x77): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN11ONE_CLASS_QD0Ev[_ZN11ONE_CLASS_QD0Ev]+0x31): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN11ONE_CLASS_QD0Ev[_ZN11ONE_CLASS_QD0Ev]+0x3f): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN11ONE_CLASS_QD0Ev[_ZN11ONE_CLASS_QD0Ev]+0x5b): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN5SVC_QD0Ev[_ZN5SVC_QD0Ev]+0x21): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVC_QD0Ev[_ZN5SVC_QD0Ev]+0x3f): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN5SVC_QD0Ev[_ZN5SVC_QD0Ev]+0x4d): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVC_QD0Ev[_ZN5SVC_QD0Ev]+0x69): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD0Ev[_ZN5SVR_QD0Ev]+0x31): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD0Ev[_ZN5SVR_QD0Ev]+0x3f): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD0Ev[_ZN5SVR_QD0Ev]+0x4d): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD0Ev[_ZN5SVR_QD0Ev]+0x5b): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD0Ev[_ZN5SVR_QD0Ev]+0x69): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD0Ev[_ZN5SVR_QD0Ev]+0x77): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD0Ev[_ZN5SVR_QD0Ev]+0x93): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.rdata$_ZTI7QMatrix[_ZTI7QMatrix]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info' svm.obj:svm.cpp:(.rdata$_ZTI6Kernel[_ZTI6Kernel]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info' svm.obj:svm.cpp:(.rdata$_ZTI6Solver[_ZTI6Solver]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info' svm.obj:svm.cpp:(.rdata$_ZTI9Solver_NU[_ZTI9Solver_NU]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info' svm.obj:svm.cpp:(.rdata$_ZTI5SVC_Q[_ZTI5SVC_Q]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info' svm.obj:svm.cpp:(.rdata$_ZTI11ONE_CLASS_Q[_ZTI11ONE_CLASS_Q]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info' svm.obj:svm.cpp:(.rdata$_ZTI5SVR_Q[_ZTI5SVR_Q]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info' svm.obj:svm.cpp:(.rdata$_ZTV6Kernel[_ZTV6Kernel]+0x10): undefined reference to `__cxa_pure_virtual' svm.obj:svm.cpp:(.rdata$_ZTV6Kernel[_ZTV6Kernel]+0x18): undefined reference to `__cxa_pure_virtual' collect2.exe: error: ld returned 1 exit status 出错 make (第 7 行) mex -O -largeArrayDims -I..\ svmtrain.c svm.obj svm_model_matlab.obj ^^^
07-28
这样,我给出原来的lcd.c/h、lcd_init.h/c,请你将每一个文件都修改成使用HAL库风格的文件,但同时,请不要做其他的修改,此外,将使用delay函数相关的代码更换为相应的hal_delay的hal库函数而不是原来的自定义函数,每个文件修改后给出完整的代码,包括所有部分,不要省略,这样我可以直接替换。 下面是lcd.c #include "lcd.h" #include "lcd_init.h" #include "lcdfont.h" #include "delay.h" /****************************************************************************** 函数说明:在指定区域填充颜色 入口数据:xsta,ysta 起始坐标 xend,yend 终止坐标 color 要填充的颜色 返回值: 无 ******************************************************************************/ void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color) { u16 i,j; LCD_Address_Set(xsta,ysta,xend-1,yend-1);//设置显示范围 for(i=ysta;i<yend;i++) { for(j=xsta;j<xend;j++) { LCD_WR_DATA(color); } } } /****************************************************************************** 函数说明:在指定位置画点 入口数据:x,y 画点坐标 color 点的颜色 返回值: 无 ******************************************************************************/ void LCD_DrawPoint(u16 x,u16 y,u16 color) { LCD_Address_Set(x,y,x,y);//设置光标位置 LCD_WR_DATA(color); } /****************************************************************************** 函数说明:画线 入口数据:x1,y1 起始坐标 x2,y2 终止坐标 color 线的颜色 返回值: 无 ******************************************************************************/ void LCD_DrawLine(u16 x1,u16 y1,u16 x2,u16 y2,u16 color) { u16 t; int xerr=0,yerr=0,delta_x,delta_y,distance; int incx,incy,uRow,uCol; delta_x=x2-x1; //计算坐标增量 delta_y=y2-y1; uRow=x1;//画线起点坐标 uCol=y1; if(delta_x>0)incx=1; //设置单步方向 else if (delta_x==0)incx=0;//垂直线 else {incx=-1;delta_x=-delta_x;} if(delta_y>0)incy=1; else if (delta_y==0)incy=0;//水平线 else {incy=-1;delta_y=-delta_y;} if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 else distance=delta_y; for(t=0;t<distance+1;t++) { LCD_DrawPoint(uRow,uCol,color);//画点 xerr+=delta_x; yerr+=delta_y; if(xerr>distance) { xerr-=distance; uRow+=incx; } if(yerr>distance) { yerr-=distance; uCol+=incy; } } } /****************************************************************************** 函数说明:画矩形 入口数据:x1,y1 起始坐标 x2,y2 终止坐标 color 矩形的颜色 返回值: 无 ******************************************************************************/ void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color) { LCD_DrawLine(x1,y1,x2,y1,color); LCD_DrawLine(x1,y1,x1,y2,color); LCD_DrawLine(x1,y2,x2,y2,color); LCD_DrawLine(x2,y1,x2,y2,color); } /****************************************************************************** 函数说明:画圆 入口数据:x0,y0 圆心坐标 r 半径 color 圆的颜色 返回值: 无 ******************************************************************************/ void Draw_Circle(u16 x0,u16 y0,u8 r,u16 color) { int a,b; a=0;b=r; while(a<=b) { LCD_DrawPoint(x0-b,y0-a,color); //3 LCD_DrawPoint(x0+b,y0-a,color); //0 LCD_DrawPoint(x0-a,y0+b,color); //1 LCD_DrawPoint(x0-a,y0-b,color); //2 LCD_DrawPoint(x0+b,y0+a,color); //4 LCD_DrawPoint(x0+a,y0-b,color); //5 LCD_DrawPoint(x0+a,y0+b,color); //6 LCD_DrawPoint(x0-b,y0+a,color); //7 a++; if((a*a+b*b)>(r*r))//判断要画的点是否过远 { b--; } } } /****************************************************************************** 函数说明:显示汉字串 入口数据:x,y显示坐标 *s 要显示的汉字串 fc 字的颜色 bc 字的背景色 sizey 字号 可选 16 24 32 mode: 0非叠加模式 1叠加模式 返回值: 无 ******************************************************************************/ void LCD_ShowChinese(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode) { while(*s!=0) { if(sizey==12) LCD_ShowChinese12x12(x,y,s,fc,bc,sizey,mode); else if(sizey==16) LCD_ShowChinese16x16(x,y,s,fc,bc,sizey,mode); else if(sizey==24) LCD_ShowChinese24x24(x,y,s,fc,bc,sizey,mode); else if(sizey==32) LCD_ShowChinese32x32(x,y,s,fc,bc,sizey,mode); else return; s+=2; x+=sizey; } } /****************************************************************************** 函数说明:显示单个12x12汉字 入口数据:x,y显示坐标 *s 要显示的汉字 fc 字的颜色 bc 字的背景色 sizey 字号 mode: 0非叠加模式 1叠加模式 返回值: 无 ******************************************************************************/ void LCD_ShowChinese12x12(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode) { u8 i,j,m=0; u16 k; u16 HZnum;//汉字数目 u16 TypefaceNum;//一个字符所占字节大小 u16 x0=x; TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey; HZnum=sizeof(tfont12)/sizeof(typFNT_GB12); //统计汉字数目 for(k=0;k<HZnum;k++) { if((tfont12[k].Index[0]==*(s))&&(tfont12[k].Index[1]==*(s+1))) { LCD_Address_Set(x,y,x+sizey-1,y+sizey-1); for(i=0;i<TypefaceNum;i++) { for(j=0;j<8;j++) { if(!mode)//非叠加方式 { if(tfont12[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc); else LCD_WR_DATA(bc); m++; if(m%sizey==0) { m=0; break; } } else//叠加方式 { if(tfont12[k].Msk[i]&(0x01<<j)) LCD_DrawPoint(x,y,fc);//画一个点 x++; if((x-x0)==sizey) { x=x0; y++; break; } } } } } continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响 } } /****************************************************************************** 函数说明:显示单个16x16汉字 入口数据:x,y显示坐标 *s 要显示的汉字 fc 字的颜色 bc 字的背景色 sizey 字号 mode: 0非叠加模式 1叠加模式 返回值: 无 ******************************************************************************/ void LCD_ShowChinese16x16(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode) { u8 i,j,m=0; u16 k; u16 HZnum;//汉字数目 u16 TypefaceNum;//一个字符所占字节大小 u16 x0=x; TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey; HZnum=sizeof(tfont16)/sizeof(typFNT_GB16); //统计汉字数目 for(k=0;k<HZnum;k++) { if ((tfont16[k].Index[0]==*(s))&&(tfont16[k].Index[1]==*(s+1))) { LCD_Address_Set(x,y,x+sizey-1,y+sizey-1); for(i=0;i<TypefaceNum;i++) { for(j=0;j<8;j++) { if(!mode)//非叠加方式 { if(tfont16[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc); else LCD_WR_DATA(bc); m++; if(m%sizey==0) { m=0; break; } } else//叠加方式 { if(tfont16[k].Msk[i]&(0x01<<j)) LCD_DrawPoint(x,y,fc);//画一个点 x++; if((x-x0)==sizey) { x=x0; y++; break; } } } } } continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响 } } /****************************************************************************** 函数说明:显示单个24x24汉字 入口数据:x,y显示坐标 *s 要显示的汉字 fc 字的颜色 bc 字的背景色 sizey 字号 mode: 0非叠加模式 1叠加模式 返回值: 无 ******************************************************************************/ void LCD_ShowChinese24x24(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode) { u8 i,j,m=0; u16 k; u16 HZnum;//汉字数目 u16 TypefaceNum;//一个字符所占字节大小 u16 x0=x; TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey; HZnum=sizeof(tfont24)/sizeof(typFNT_GB24); //统计汉字数目 for(k=0;k<HZnum;k++) { if ((tfont24[k].Index[0]==*(s))&&(tfont24[k].Index[1]==*(s+1))) { LCD_Address_Set(x,y,x+sizey-1,y+sizey-1); for(i=0;i<TypefaceNum;i++) { for(j=0;j<8;j++) { if(!mode)//非叠加方式 { if(tfont24[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc); else LCD_WR_DATA(bc); m++; if(m%sizey==0) { m=0; break; } } else//叠加方式 { if(tfont24[k].Msk[i]&(0x01<<j)) LCD_DrawPoint(x,y,fc);//画一个点 x++; if((x-x0)==sizey) { x=x0; y++; break; } } } } } continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响 } } /****************************************************************************** 函数说明:显示单个32x32汉字 入口数据:x,y显示坐标 *s 要显示的汉字 fc 字的颜色 bc 字的背景色 sizey 字号 mode: 0非叠加模式 1叠加模式 返回值: 无 ******************************************************************************/ void LCD_ShowChinese32x32(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode) { u8 i,j,m=0; u16 k; u16 HZnum;//汉字数目 u16 TypefaceNum;//一个字符所占字节大小 u16 x0=x; TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey; HZnum=sizeof(tfont32)/sizeof(typFNT_GB32); //统计汉字数目 for(k=0;k<HZnum;k++) { if ((tfont32[k].Index[0]==*(s))&&(tfont32[k].Index[1]==*(s+1))) { LCD_Address_Set(x,y,x+sizey-1,y+sizey-1); for(i=0;i<TypefaceNum;i++) { for(j=0;j<8;j++) { if(!mode)//非叠加方式 { if(tfont32[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc); else LCD_WR_DATA(bc); m++; if(m%sizey==0) { m=0; break; } } else//叠加方式 { if(tfont32[k].Msk[i]&(0x01<<j)) LCD_DrawPoint(x,y,fc);//画一个点 x++; if((x-x0)==sizey) { x=x0; y++; break; } } } } } continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响 } } /****************************************************************************** 函数说明:显示单个字符 入口数据:x,y显示坐标 num 要显示的字符 fc 字的颜色 bc 字的背景色 sizey 字号 mode: 0非叠加模式 1叠加模式 返回值: 无 ******************************************************************************/ void LCD_ShowChar(u16 x,u16 y,u8 num,u16 fc,u16 bc,u8 sizey,u8 mode) { u8 temp,sizex,t,m=0; u16 i,TypefaceNum;//一个字符所占字节大小 u16 x0=x; sizex=sizey/2; TypefaceNum=(sizex/8+((sizex%8)?1:0))*sizey; num=num-' '; //得到偏移后的值 LCD_Address_Set(x,y,x+sizex-1,y+sizey-1); //设置光标位置 for(i=0;i<TypefaceNum;i++) { if(sizey==12)temp=ascii_1206[num][i]; //调用6x12字体 else if(sizey==16)temp=ascii_1608[num][i]; //调用8x16字体 else if(sizey==24)temp=ascii_2412[num][i]; //调用12x24字体 else if(sizey==32)temp=ascii_3216[num][i]; //调用16x32字体 else return; for(t=0;t<8;t++) { if(!mode)//非叠加模式 { if(temp&(0x01<<t))LCD_WR_DATA(fc); else LCD_WR_DATA(bc); m++; if(m%sizex==0) { m=0; break; } } else//叠加模式 { if(temp&(0x01<<t))LCD_DrawPoint(x,y,fc);//画一个点 x++; if((x-x0)==sizex) { x=x0; y++; break; } } } } } /****************************************************************************** 函数说明:显示字符串 入口数据:x,y显示坐标 *p 要显示的字符串 fc 字的颜色 bc 字的背景色 sizey 字号 mode: 0非叠加模式 1叠加模式 返回值: 无 ******************************************************************************/ void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 fc,u16 bc,u8 sizey,u8 mode) { while(*p!='\0') { LCD_ShowChar(x,y,*p,fc,bc,sizey,mode); x+=sizey/2; p++; } } /****************************************************************************** 函数说明:显示数字 入口数据:m底数,n指数 返回值: 无 ******************************************************************************/ u32 mypow(u8 m,u8 n) { u32 result=1; while(n--)result*=m; return result; } /****************************************************************************** 函数说明:显示整数变量 入口数据:x,y显示坐标 num 要显示整数变量 len 要显示的位数 fc 字的颜色 bc 字的背景色 sizey 字号 返回值: 无 ******************************************************************************/ void LCD_ShowIntNum(u16 x,u16 y,u16 num,u8 len,u16 fc,u16 bc,u8 sizey) { u8 t,temp; u8 enshow=0; u8 sizex=sizey/2; for(t=0;t<len;t++) { temp=(num/mypow(10,len-t-1))%10; if(enshow==0&&t<(len-1)) { if(temp==0) { LCD_ShowChar(x+t*sizex,y,' ',fc,bc,sizey,0); continue; }else enshow=1; } LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0); } } /****************************************************************************** 函数说明:显示两位小数变量 入口数据:x,y显示坐标 num 要显示小数变量 len 要显示的位数 fc 字的颜色 bc 字的背景色 sizey 字号 返回值: 无 ******************************************************************************/ void LCD_ShowFloatNum1(u16 x,u16 y,float num,u8 len,u16 fc,u16 bc,u8 sizey) { u8 t,temp,sizex; u16 num1; sizex=sizey/2; num1=num*100; for(t=0;t<len;t++) { temp=(num1/mypow(10,len-t-1))%10; if(t==(len-2)) { LCD_ShowChar(x+(len-2)*sizex,y,'.',fc,bc,sizey,0); t++; len+=1; } LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0); } } /****************************************************************************** 函数说明:显示图片 入口数据:x,y起点坐标 length 图片长度 width 图片宽度 pic[] 图片数组 返回值: 无 ******************************************************************************/ void LCD_ShowPicture(u16 x,u16 y,u16 length,u16 width,const u8 pic[]) { u16 i,j; u32 k=0; LCD_Address_Set(x,y,x+length-1,y+width-1); for(i=0;i<length;i++) { for(j=0;j<width;j++) { LCD_WR_DATA8(pic[k*2]); LCD_WR_DATA8(pic[k*2+1]); k++; } } } 下面是lcd.h #ifndef __LCD_H #define __LCD_H #include "sys.h" void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color);//指定区域填充颜色 void LCD_DrawPoint(u16 x,u16 y,u16 color);//在指定位置画一个点 void LCD_DrawLine(u16 x1,u16 y1,u16 x2,u16 y2,u16 color);//在指定位置画一条线 void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color);//在指定位置画一个矩形 void Draw_Circle(u16 x0,u16 y0,u8 r,u16 color);//在指定位置画一个圆 void LCD_ShowChinese(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示汉字串 void LCD_ShowChinese12x12(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个12x12汉字 void LCD_ShowChinese16x16(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个16x16汉字 void LCD_ShowChinese24x24(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个24x24汉字 void LCD_ShowChinese32x32(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个32x32汉字 void LCD_ShowChar(u16 x,u16 y,u8 num,u16 fc,u16 bc,u8 sizey,u8 mode);//显示一个字符 void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 fc,u16 bc,u8 sizey,u8 mode);//显示字符串 u32 mypow(u8 m,u8 n);//求幂 void LCD_ShowIntNum(u16 x,u16 y,u16 num,u8 len,u16 fc,u16 bc,u8 sizey);//显示整数变量 void LCD_ShowFloatNum1(u16 x,u16 y,float num,u8 len,u16 fc,u16 bc,u8 sizey);//显示两位小数变量 void LCD_ShowPicture(u16 x,u16 y,u16 length,u16 width,const u8 pic[]);//显示图片 //画笔颜色 #define WHITE 0xFFFF #define BLACK 0x0000 #define BLUE 0x001F #define BRED 0XF81F #define GRED 0XFFE0 #define GBLUE 0X07FF #define RED 0xF800 #define MAGENTA 0xF81F #define GREEN 0x07E0 #define CYAN 0x7FFF #define YELLOW 0xFFE0 #define BROWN 0XBC40 //棕色 #define BRRED 0XFC07 //棕红色 #define GRAY 0X8430 //灰色 #define DARKBLUE 0X01CF //深蓝色 #define LIGHTBLUE 0X7D7C //浅蓝色 #define GRAYBLUE 0X5458 //灰蓝色 #define LIGHTGREEN 0X841F //浅绿色 #define LGRAY 0XC618 //浅灰色(PANNEL),窗体背景色 #define LGRAYBLUE 0XA651 //浅灰蓝色(中间层颜色) #define LBBLUE 0X2B12 //浅棕蓝色(选择条目的反色) #endif 下面是lcd_init.c #include "lcd_init.h" #include "delay.h" void LCD_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOG, ENABLE);//使能PORTA~E,PORTG时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化 GPIO_SetBits(GPIOG,GPIO_Pin_12); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_15 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化 GPIO_SetBits(GPIOD,GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_15); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化 GPIO_SetBits(GPIOE,GPIO_Pin_8|GPIO_Pin_10); } /****************************************************************************** 函数说明:LCD串行数据写入函数 入口数据:dat 要写入的串行数据 返回值: 无 ******************************************************************************/ void LCD_Writ_Bus(u8 dat) { u8 i; LCD_CS_Clr(); for(i=0;i<8;i++) { LCD_SCLK_Clr(); if(dat&0x80) { LCD_MOSI_Set(); } else { LCD_MOSI_Clr(); } LCD_SCLK_Set(); dat<<=1; } LCD_CS_Set(); } /****************************************************************************** 函数说明:LCD写入数据 入口数据:dat 写入的数据 返回值: 无 ******************************************************************************/ void LCD_WR_DATA8(u8 dat) { LCD_Writ_Bus(dat); } /****************************************************************************** 函数说明:LCD写入数据 入口数据:dat 写入的数据 返回值: 无 ******************************************************************************/ void LCD_WR_DATA(u16 dat) { LCD_Writ_Bus(dat>>8); LCD_Writ_Bus(dat); } /****************************************************************************** 函数说明:LCD写入命令 入口数据:dat 写入的命令 返回值: 无 ******************************************************************************/ void LCD_WR_REG(u8 dat) { LCD_DC_Clr();//写命令 LCD_Writ_Bus(dat); LCD_DC_Set();//写数据 } /****************************************************************************** 函数说明:设置起始结束地址 入口数据:x1,x2 设置列的起始结束地址 y1,y2 设置行的起始结束地址 返回值: 无 ******************************************************************************/ void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2) { if(USE_HORIZONTAL==0) { LCD_WR_REG(0x2a);//列地址设置 LCD_WR_DATA(x1+2); LCD_WR_DATA(x2+2); LCD_WR_REG(0x2b);//行地址设置 LCD_WR_DATA(y1+1); LCD_WR_DATA(y2+1); LCD_WR_REG(0x2c);//储存器写 } else if(USE_HORIZONTAL==1) { LCD_WR_REG(0x2a);//列地址设置 LCD_WR_DATA(x1+2); LCD_WR_DATA(x2+2); LCD_WR_REG(0x2b);//行地址设置 LCD_WR_DATA(y1+1); LCD_WR_DATA(y2+1); LCD_WR_REG(0x2c);//储存器写 } else if(USE_HORIZONTAL==2) { LCD_WR_REG(0x2a);//列地址设置 LCD_WR_DATA(x1+1); LCD_WR_DATA(x2+1); LCD_WR_REG(0x2b);//行地址设置 LCD_WR_DATA(y1+2); LCD_WR_DATA(y2+2); LCD_WR_REG(0x2c);//储存器写 } else { LCD_WR_REG(0x2a);//列地址设置 LCD_WR_DATA(x1+1); LCD_WR_DATA(x2+1); LCD_WR_REG(0x2b);//行地址设置 LCD_WR_DATA(y1+2); LCD_WR_DATA(y2+2); LCD_WR_REG(0x2c);//储存器写 } } void LCD_Init(void) { LCD_GPIO_Init();//初始化GPIO LCD_RES_Clr();//复位 delay_ms(100); LCD_RES_Set(); delay_ms(100); LCD_BLK_Set();//打开背光 delay_ms(100); //************* Start Initial Sequence **********// LCD_WR_REG(0x11); //Sleep out delay_ms(120); //Delay 120ms //------------------------------------ST7735S Frame Rate-----------------------------------------// LCD_WR_REG(0xB1); LCD_WR_DATA8(0x05); LCD_WR_DATA8(0x3C); LCD_WR_DATA8(0x3C); LCD_WR_REG(0xB2); LCD_WR_DATA8(0x05); LCD_WR_DATA8(0x3C); LCD_WR_DATA8(0x3C); LCD_WR_REG(0xB3); LCD_WR_DATA8(0x05); LCD_WR_DATA8(0x3C); LCD_WR_DATA8(0x3C); LCD_WR_DATA8(0x05); LCD_WR_DATA8(0x3C); LCD_WR_DATA8(0x3C); //------------------------------------End ST7735S Frame Rate---------------------------------// LCD_WR_REG(0xB4); //Dot inversion LCD_WR_DATA8(0x03); //------------------------------------ST7735S Power Sequence---------------------------------// LCD_WR_REG(0xC0); LCD_WR_DATA8(0x28); LCD_WR_DATA8(0x08); LCD_WR_DATA8(0x04); LCD_WR_REG(0xC1); LCD_WR_DATA8(0XC0); LCD_WR_REG(0xC2); LCD_WR_DATA8(0x0D); LCD_WR_DATA8(0x00); LCD_WR_REG(0xC3); LCD_WR_DATA8(0x8D); LCD_WR_DATA8(0x2A); LCD_WR_REG(0xC4); LCD_WR_DATA8(0x8D); LCD_WR_DATA8(0xEE); //---------------------------------End ST7735S Power Sequence-------------------------------------// LCD_WR_REG(0xC5); //VCOM LCD_WR_DATA8(0x1A); LCD_WR_REG(0x36); //MX, MY, RGB mode if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x00); else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC0); else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x70); else LCD_WR_DATA8(0xA0); //------------------------------------ST7735S Gamma Sequence---------------------------------// LCD_WR_REG(0xE0); LCD_WR_DATA8(0x04); LCD_WR_DATA8(0x22); LCD_WR_DATA8(0x07); LCD_WR_DATA8(0x0A); LCD_WR_DATA8(0x2E); LCD_WR_DATA8(0x30); LCD_WR_DATA8(0x25); LCD_WR_DATA8(0x2A); LCD_WR_DATA8(0x28); LCD_WR_DATA8(0x26); LCD_WR_DATA8(0x2E); LCD_WR_DATA8(0x3A); LCD_WR_DATA8(0x00); LCD_WR_DATA8(0x01); LCD_WR_DATA8(0x03); LCD_WR_DATA8(0x13); LCD_WR_REG(0xE1); LCD_WR_DATA8(0x04); LCD_WR_DATA8(0x16); LCD_WR_DATA8(0x06); LCD_WR_DATA8(0x0D); LCD_WR_DATA8(0x2D); LCD_WR_DATA8(0x26); LCD_WR_DATA8(0x23); LCD_WR_DATA8(0x27); LCD_WR_DATA8(0x27); LCD_WR_DATA8(0x25); LCD_WR_DATA8(0x2D); LCD_WR_DATA8(0x3B); LCD_WR_DATA8(0x00); LCD_WR_DATA8(0x01); LCD_WR_DATA8(0x04); LCD_WR_DATA8(0x13); //------------------------------------End ST7735S Gamma Sequence-----------------------------// LCD_WR_REG(0x3A); //65k mode LCD_WR_DATA8(0x05); LCD_WR_REG(0x29); //Display on } 下面是lcd_init.h #ifndef __LCD_INIT_H #define __LCD_INIT_H #include "sys.h" #define USE_HORIZONTAL 1 //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏 #if USE_HORIZONTAL==0||USE_HORIZONTAL==1 #define LCD_W 128 #define LCD_H 160 #else #define LCD_W 160 #define LCD_H 128 #endif //-----------------LCD端口定义---------------- #define LCD_SCLK_Clr() GPIO_ResetBits(GPIOG,GPIO_Pin_12)//SCL=SCLK #define LCD_SCLK_Set() GPIO_SetBits(GPIOG,GPIO_Pin_12) #define LCD_MOSI_Clr() GPIO_ResetBits(GPIOD,GPIO_Pin_5)//SDA=MOSI #define LCD_MOSI_Set() GPIO_SetBits(GPIOD,GPIO_Pin_5) #define LCD_RES_Clr() GPIO_ResetBits(GPIOD,GPIO_Pin_4)//RES #define LCD_RES_Set() GPIO_SetBits(GPIOD,GPIO_Pin_4) #define LCD_DC_Clr() GPIO_ResetBits(GPIOD,GPIO_Pin_15)//DC #define LCD_DC_Set() GPIO_SetBits(GPIOD,GPIO_Pin_15) #define LCD_CS_Clr() GPIO_ResetBits(GPIOD,GPIO_Pin_1)//CS #define LCD_CS_Set() GPIO_SetBits(GPIOD,GPIO_Pin_1) #define LCD_BLK_Clr() GPIO_ResetBits(GPIOE,GPIO_Pin_8)//BLK #define LCD_BLK_Set() GPIO_SetBits(GPIOE,GPIO_Pin_8) void LCD_GPIO_Init(void);//初始化GPIO void LCD_Writ_Bus(u8 dat);//模拟SPI时序 void LCD_WR_DATA8(u8 dat);//写入一个字节 void LCD_WR_DATA(u16 dat);//写入两个字节 void LCD_WR_REG(u8 dat);//写入一个指令 void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2);//设置坐标函数 void LCD_Init(void);//LCD初始化 #endif 刚才漏了sys.csys.h,也帮我一并修改了 下面是sys.c #include "sys.h" //THUMB指令不支持汇编内联 //采用如下方法实现执行汇编指令WFI __asm void WFI_SET(void) { WFI; } //关闭所有中断(但是不包括faultNMI中断) __asm void INTX_DISABLE(void) { CPSID I BX LR } //开启所有中断 __asm void INTX_ENABLE(void) { CPSIE I BX LR } //设置栈顶地址 //addr:栈顶地址 __asm void MSR_MSP(u32 addr) { MSR MSP, r0 //set Main Stack value BX r14 } 下面是sys.h #ifndef __SYS_H #define __SYS_H #include "stm32f4xx.h" #include "stm32f4xx_hal.h" //0,不支持ucos //1,支持ucos #define SYSTEM_SUPPORT_OS 0 //定义系统文件夹是否支持UCOS //位带操作,实现51类似的GPIO控制功能 //具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).M4同M3类似,只是寄存器地址变了. //IO口操作宏定义 #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) #define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) //IO口地址映射 #define GPIOA_ODR_Addr (GPIOA_BASE+20) //0x40020014 #define GPIOB_ODR_Addr (GPIOB_BASE+20) //0x40020414 #define GPIOC_ODR_Addr (GPIOC_BASE+20) //0x40020814 #define GPIOD_ODR_Addr (GPIOD_BASE+20) //0x40020C14 #define GPIOE_ODR_Addr (GPIOE_BASE+20) //0x40021014 #define GPIOF_ODR_Addr (GPIOF_BASE+20) //0x40021414 #define GPIOG_ODR_Addr (GPIOG_BASE+20) //0x40021814 #define GPIOH_ODR_Addr (GPIOH_BASE+20) //0x40021C14 #define GPIOI_ODR_Addr (GPIOI_BASE+20) //0x40022014 #define GPIOA_IDR_Addr (GPIOA_BASE+16) //0x40020010 #define GPIOB_IDR_Addr (GPIOB_BASE+16) //0x40020410 #define GPIOC_IDR_Addr (GPIOC_BASE+16) //0x40020810 #define GPIOD_IDR_Addr (GPIOD_BASE+16) //0x40020C10 #define GPIOE_IDR_Addr (GPIOE_BASE+16) //0x40021010 #define GPIOF_IDR_Addr (GPIOF_BASE+16) //0x40021410 #define GPIOG_IDR_Addr (GPIOG_BASE+16) //0x40021810 #define GPIOH_IDR_Addr (GPIOH_BASE+16) //0x40021C10 #define GPIOI_IDR_Addr (GPIOI_BASE+16) //0x40022010 //IO口操作,只对单一的IO口! //确保n的值小于16! #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出 #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入 #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出 #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入 #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出 #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入 #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出 #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入 #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出 #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入 #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出 #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入 #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出 #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入 #define PHout(n) BIT_ADDR(GPIOH_ODR_Addr,n) //输出 #define PHin(n) BIT_ADDR(GPIOH_IDR_Addr,n) //输入 #define PIout(n) BIT_ADDR(GPIOI_ODR_Addr,n) //输出 #define PIin(n) BIT_ADDR(GPIOI_IDR_Addr,n) //输入 //以下为汇编函数 void WFI_SET(void); //执行WFI指令 void INTX_DISABLE(void);//关闭所有中断 void INTX_ENABLE(void); //开启所有中断 void MSR_MSP(uint32_t addr); //设置堆栈地址 #endif
07-12
发现yaw的值在一定时间后会被锁死(oled屏幕上数字不发生改变),查找原因,查找原因修正 empty.c #include <math.h> // 添加数学库用于fabs函数 #include "board.h" #include "my_key.h" #include "my_time.h" #include "ti_msp_dl_config.h" #include "oled.h" void BUZZY_OFF(void) { DL_GPIO_setPins(BUZZY_PORT, BUZZY_PIN_PIN); } void BUZZY_ON(void) { DL_GPIO_clearPins(BUZZY_PORT, BUZZY_PIN_PIN); } void refresh_oled(void); void key(void); void go_straight(int dis); void go_arc_ccd(hsu_time_t); void go_brc_ccd(hsu_time_t); void turn_in_place(float angle); void sound_light_alert(void); void show_task_now(void); u8 Car_Mode = Diff_Car; int Motor_Left, Motor_Right; // 电机PWM变量 应是Motor的 u8 PID_Send; // 延时调参相关变量 float RC_Velocity = 200, RC_Turn_Velocity, Move_X, Move_Y, Move_Z, PS2_ON_Flag; // 遥控控制的速度 float Velocity_Left, Velocity_Right; // 车轮速度(mm/s) u16 test_num, show_cnt; float Voltage = 0; extern float Yaw; // 声明外部YAW角度变量 int64_t left_encoder = 0, right_encoder = 0; void SysTick_Handler(void) { hsu_time_systick_handler(); } typedef enum { BEGIN, T1, T2, T3, T4 } TaskState; typedef enum { STOP, GO_STRAIGHT, GO_CCD, TURN_IN_PLACE, WAIT_ALERT } DoingWhat; typedef struct __TASK_NAMESPACE { uint8_t is; uint8_t is_running; uint8_t finish; uint8_t sub_finish; uint8_t running_state; // 0: 停止, 1: 运行中 TaskState state; DoingWhat doing_what; float target; float vx; float vz; // 用于复杂任务 uint8_t sub_task_stage; // 子任务阶段 uint8_t lap_count; // 圈数计数 int64_t start_encoder; // 起始编码器值 uint32_t alert_start_time; // 声光提示开始时间 float start_yaw; // 起始YAW角度 float target_yaw_diff; // 目标YAW角度差 hsu_time_t ccd_end_time; } TaskNamespace; void reset_task_namespace(TaskNamespace *t) { t->is_running = 0; t->finish = 0; t->sub_finish = 0; t->state = BEGIN; t->doing_what = STOP; t->vx = 0; t->vz = 0; t->sub_task_stage = 0; t->lap_count = 0; t->start_encoder = left_encoder; t->alert_start_time = 0; t->start_yaw = 0; t->target_yaw_diff = 0; t->running_state = 0; // 明确重置运行状态为0 t->ccd_end_time = 0; t->is = 0; } void next_state(TaskNamespace *t) { TaskState last_state = t->state; reset_task_namespace(t); if (last_state < T4) { t->state = last_state + 1; } } TaskNamespace task_namespace; void show_task_now(void) { //OLED_ShowString(0, 0, "Task Now:"); switch (task_namespace.state) { case BEGIN: OLED_ShowString(1, 10,"0"); break; case T1: OLED_ShowString(1, 10,"1"); break; case T2: OLED_ShowString(1, 10,"2"); break; case T3: OLED_ShowString(1, 10,"3"); break; case T4: OLED_ShowString(1, 10,"4"); break; default: break; } } void main_task(void); int main(void) { // 系统初始化 SYSCFG_DL_init(); // 初始化系统配置 hsu_time_init(); // 时间 // 清除所有外设的中断挂起状态 NVIC_ClearPendingIRQ(ENCODERA_INT_IRQN); // 编码器A中断 NVIC_ClearPendingIRQ(ENCODERB_INT_IRQN); // 编码器B中断 NVIC_ClearPendingIRQ(UART_0_INST_INT_IRQN); // UART0串口中断 // 使能各外设的中断 NVIC_EnableIRQ(ENCODERA_INT_IRQN); // 开启编码器A中断 NVIC_EnableIRQ(ENCODERB_INT_IRQN); // 开启编码器B中断 NVIC_EnableIRQ(UART_0_INST_INT_IRQN); // 开启UART0中断 reset_task_namespace(&task_namespace); task_namespace.state = BEGIN; // 明确设置初始状态 // 定时器ADC相关中断配置 NVIC_ClearPendingIRQ(TIMER_0_INST_INT_IRQN); // 清除定时器0中断挂起 NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN); // 开启定时器0中断 NVIC_EnableIRQ(ADC12_VOLTAGE_INST_INT_IRQN); NVIC_EnableIRQ(ADC12_CCD_INST_INT_IRQN); OLED_Init(); // 初始化OLED显示屏 OLED_ShowString(1, 1, "Task Now:"); OLED_ShowString(2, 1, "state:"); OLED_ShowString(3, 1, "yaw:"); MPU6050_initialize(); DMP_Init(); BUZZY_ON(); // 主循环 // printf("Test delay 500us\n"); // hsu_time_delay_us(500); // printf("Test delay 500us end\n"); uint8_t main_task_timer = hsu_time_timer_create(10, true, main_task); hsu_time_timer_start(main_task_timer); uint8_t refresh_oled_timer = hsu_time_timer_create(5, true, refresh_oled); hsu_time_timer_start(refresh_oled_timer); uint8_t key_timer = hsu_time_timer_create(2, true, key); hsu_time_timer_start(key_timer); while (1) { hsu_time_timer_process(); RD_TSL(); // 读取CCD数据 Find_CCD_Median(); // 计算CCD数据中值 Read_DMP(); show_task_now(); char yaw_str[10]; // 存储格式化后的字符串 snprintf(yaw_str, sizeof(yaw_str), "%.1f", Yaw); // 格式化为带一位小数的字符串 OLED_ShowString(3, 6, yaw_str); // 在指定位置显示YAW值 //DL_GPIO_togglePins(LED_PORT, LED_led_PIN); // printf("L=%lld R=%lld YAW=%.1f\n", left_encoder, right_encoder, Yaw); } } void task_no(void); void task_1(void); void task_2(void); void task_3(void); void task_4(void); void main_task(void) { if (!(task_namespace.is)) return; printf("main task\n"); switch (task_namespace.state) { case BEGIN: task_no(); break; case T1: task_1(); break; case T2: task_2(); break; case T3: task_3(); break; case T4: task_4(); break; default: break; } switch (task_namespace.doing_what) { case STOP: Get_Target_Encoder(0, 0); break; case GO_STRAIGHT: if ((left_encoder * 1.f) < task_namespace.target) { Get_Target_Encoder(0.3, 0); // 提高速度到300mm/s } else { Get_Target_Encoder(0, 0); task_namespace.doing_what = STOP; task_namespace.finish = 1; } break; case GO_CCD: if (task_namespace.ccd_end_time < hsu_time_get_ms()) { Get_Target_Encoder(0, 0); task_namespace.doing_what = STOP; task_namespace.finish = 1; } else { CCD_Mode(); } break; case TURN_IN_PLACE: // 原地转向控制 if (task_namespace.target_yaw_diff != 0) { float current_yaw_diff = Yaw - task_namespace.start_yaw; // 处理角度跨越±180度的情况 if (current_yaw_diff > 180) { current_yaw_diff -= 360; } else if (current_yaw_diff < -180) { current_yaw_diff += 360; } printf("Turn: Start=%.1f Current=%.1f Diff=%.1f Target=%.1f\n", task_namespace.start_yaw, Yaw, current_yaw_diff, task_namespace.target_yaw_diff); // 检查是否达到目标角度 if ((task_namespace.target_yaw_diff > 0 && current_yaw_diff >= task_namespace.target_yaw_diff) || (task_namespace.target_yaw_diff < 0 && current_yaw_diff <= task_namespace.target_yaw_diff)) { Get_Target_Encoder(0, 0); // 停止转向 task_namespace.doing_what = STOP; task_namespace.finish = 1; } else { // 继续转向 float turn_speed = (task_namespace.target_yaw_diff > 0) ? 0.1 : -0.1; Get_Target_Encoder(0, turn_speed); } } break; case WAIT_ALERT: Get_Target_Encoder(0, 0); // 停车 if (hsu_time_get_ms() - task_namespace.alert_start_time > 1000) { // 声光提示1秒 task_namespace.doing_what = STOP; task_namespace.finish = 1; } break; default: break; } } void task_no(void) { return; } // 任务1:A点到B点直线行驶 void task_1(void) { if (!task_namespace.is_running) { task_namespace.is_running = 1; task_namespace.sub_task_stage = 0; task_namespace.finish = 1; return; } if (task_namespace.finish) { switch (task_namespace.sub_task_stage) { case 0: // 开始第一阶段:A到B go_straight(300); break; case 1: // A到B完成,开始B到C DL_GPIO_togglePins(LED_PORT, LED_led_PIN); break; case 2: //任务结束 reset_task_namespace(&task_namespace); task_namespace.running_state = 0; // 重置为停止状态 break; } task_namespace.finish = 0; task_namespace.sub_task_stage++; } return; } // 任务2:A->B->C->D->A循环 void task_2(void) { if (!task_namespace.is_running) { task_namespace.is_running = 1; task_namespace.sub_task_stage = 0; task_namespace.finish = 1; return; } if (task_namespace.finish) { switch (task_namespace.sub_task_stage) { case 0: // 开始第一阶段:A到B go_straight(3300); break; case 1: //DL_GPIO_togglePins(LED_PORT, LED_led_PIN); go_straight(2000); break; case 2: // B到C弧线完成,开始C到D直线 sound_light_alert(); //turn_in_place(-17.0f); go_straight(2980); break; case 3: // C到D完成,开始D到A弧线 sound_light_alert(); go_arc_ccd(3530); break; case 4: // D到A弧线完成,任务结束 sound_light_alert(); reset_task_namespace(&task_namespace); break; } task_namespace.finish = 0; task_namespace.sub_task_stage++; } return; } // 任务3:A->C->B->D->A循环 void task_3(void) { if (!task_namespace.is_running) { task_namespace.is_running = 1; task_namespace.sub_task_stage = 0; task_namespace.finish = 1; return; } if (task_namespace.finish) { switch (task_namespace.sub_task_stage) { case 0: turn_in_place(-31.0f); break; case 1: go_straight(4060); break; case 2: turn_in_place(30.0f); break; case 3: // 开始C到B弧线 sound_light_alert(); //go_straight(40); go_brc_ccd(3550); break; case 4: turn_in_place(36.0f); break; case 5: sound_light_alert(); go_straight(3985); break; case 6: turn_in_place(-40.0f); break; case 7: // 开始C到B弧线 sound_light_alert(); go_arc_ccd(3600); break; case 8: // D到A弧线完成,任务结束 sound_light_alert(); reset_task_namespace(&task_namespace); break; } task_namespace.finish = 0; task_namespace.sub_task_stage++; } return; } // 任务4:重复任务3路径4圈 void task_4(void) { if (!task_namespace.is_running) { task_namespace.is_running = 1; task_namespace.sub_task_stage = 0; task_namespace.finish = 1; return; } if (task_namespace.finish) { switch (task_namespace.sub_task_stage) { case 0: turn_in_place(-30.0f); break; case 1: go_straight(4045); break; case 2: turn_in_place(29.0f); break; case 3: // 开始C到B弧线 sound_light_alert(); //go_straight(40); go_brc_ccd(5000); break; case 4: turn_in_place(34.0f); break; case 5: sound_light_alert(); go_straight(4035); break; case 6: turn_in_place(-33.0f); break; case 7: // 开始C到B弧线 sound_light_alert(); go_arc_ccd(5000); break; case 8: // D到A弧线完成,任务结束 sound_light_alert(); reset_task_namespace(&task_namespace); break; } task_namespace.finish = 0; task_namespace.sub_task_stage++; } } void TIMER_0_INST_IRQHandler(void) { if (DL_TimerA_getPendingInterrupt(TIMER_0_INST)) { if (DL_TIMER_IIDX_ZERO) { Get_Velocity_From_Encoder(Get_Encoder_countA, Get_Encoder_countB); Get_Encoder_countA = Get_Encoder_countB = 0; MotorA.Motor_Pwm = Incremental_PI_Left(MotorA.Current_Encoder, MotorA.Target_Encoder); MotorB.Motor_Pwm = Incremental_PI_Right(MotorB.Current_Encoder, MotorB.Target_Encoder); if (!Flag_Stop) { Set_PWM(-MotorA.Motor_Pwm, -MotorB.Motor_Pwm); } else { Set_PWM(0, 0); } } } } uint32_t gpio_interrup1, gpio_interrup2; int64_t B1, B2, B3, B4; int64_t A1, A2, A3, A4; void GROUP1_IRQHandler(void) { // 获取中断信号 gpio_interrup1 = DL_GPIO_getEnabledInterruptStatus(ENCODERA_PORT, ENCODERA_E1A_PIN | ENCODERA_E1B_PIN); gpio_interrup2 = DL_GPIO_getEnabledInterruptStatus(ENCODERB_PORT, ENCODERB_E2A_PIN | ENCODERB_E2B_PIN); // encoderB if ((gpio_interrup1 & ENCODERA_E1A_PIN) == ENCODERA_E1A_PIN) { if (!DL_GPIO_readPins(ENCODERA_PORT, ENCODERA_E1B_PIN)) { right_encoder--; Get_Encoder_countB--; } else { right_encoder++; Get_Encoder_countB++; } } else if ((gpio_interrup1 & ENCODERA_E1B_PIN) == ENCODERA_E1B_PIN) { if (!DL_GPIO_readPins(ENCODERA_PORT, ENCODERA_E1A_PIN)) { right_encoder++; Get_Encoder_countB++; } else { right_encoder--; Get_Encoder_countB--; } } // encoderA if ((gpio_interrup2 & ENCODERB_E2A_PIN) == ENCODERB_E2A_PIN) { if (!DL_GPIO_readPins(ENCODERB_PORT, ENCODERB_E2B_PIN)) { left_encoder++; Get_Encoder_countA--; } else { left_encoder--; Get_Encoder_countA++; } } else if ((gpio_interrup2 & ENCODERB_E2B_PIN) == ENCODERB_E2B_PIN) { if (!DL_GPIO_readPins(ENCODERB_PORT, ENCODERB_E2A_PIN)) { left_encoder--; Get_Encoder_countA++; } else { left_encoder++; Get_Encoder_countA--; } } DL_GPIO_clearInterruptStatus(ENCODERA_PORT, ENCODERA_E1A_PIN | ENCODERA_E1B_PIN); DL_GPIO_clearInterruptStatus(ENCODERB_PORT, ENCODERB_E2A_PIN | ENCODERB_E2B_PIN); } // 直线行驶函数 void go_straight(int dis) { task_namespace.doing_what = GO_STRAIGHT; task_namespace.target = left_encoder + dis; task_namespace.finish = 0; } // 原地转向函数 void turn_in_place(float angle) { task_namespace.doing_what = TURN_IN_PLACE; task_namespace.start_yaw = Yaw; task_namespace.target_yaw_diff = angle; // 正值右转,负值左转 task_namespace.finish = 0; } // CCD巡线函数(需要外部条件结束) void go_ccd_line(void) { task_namespace.doing_what = GO_CCD; task_namespace.start_encoder = left_encoder; task_namespace.finish = 0; // 设置一个安全的最大距离,防止无限巡线 // 可以根据实际场地调整这个值 static uint32_t ccd_end_time = 0; if (ccd_end_time == 0) { ccd_end_time = hsu_time_get_ms(); } // 如果巡线时间超过10秒或距离超过2000mm,强制结束 if (hsu_time_get_ms() - ccd_end_time > 10000 || (left_encoder * 1.f - task_namespace.start_encoder) > 2000) { task_namespace.finish = 1; ccd_end_time = 0; } } // 弧线CCD巡线函数 void go_arc_ccd(hsu_time_t time) { task_namespace.doing_what = GO_CCD; task_namespace.start_encoder = left_encoder; task_namespace.ccd_end_time = hsu_time_get_ms() + time; } void go_brc_ccd(hsu_time_t time) { task_namespace.doing_what = GO_CCD; task_namespace.start_encoder = right_encoder; task_namespace.ccd_end_time = hsu_time_get_ms() + time; } // 声光提示函数 void sound_light_alert(void) { DL_GPIO_togglePins(LED_PORT, LED_led_PIN); DL_GPIO_setPins(BUZZY_PORT, BUZZY_PIN_PIN); uint32_t start_time = hsu_time_get_ms(); while (hsu_time_get_ms() - start_time < 1000) { // 空循环等待1秒 } //hsu_time_delay_ms(200); DL_GPIO_togglePins(LED_PORT, LED_led_PIN); DL_GPIO_clearPins(BUZZY_PORT, BUZZY_PIN_PIN); } // callback void refresh_oled(void) { show_task_now(); OLED_ShowString(2, 1, "state:"); if (task_namespace.running_state) { OLED_ShowString(2, 7, "1"); // 运行中 } else { OLED_ShowString(2, 7, "0"); // 停止 } } uint32_t key_get_tick_ms(void) { return hsu_time_get_ms(); } void key(void) { key_event_t event = key_scan(); //uint8_t key_value = key_read_pin(); // 获取按键状态 //S1 switch (event) { case KEY_EVENT_SINGLE_CLICK: next_state(&task_namespace); break; case KEY_EVENT_DOUBLE_CLICK: task_namespace.is = 1; task_namespace.running_state = 1; task_namespace.is_running = 0; // 重置任务运行标志 break; } } MPU6050.c #include "MPU6050.h" #include <stdio.h> #include "inv_mpu.h" // #include "IOI2C.h" // #include "usart.h" #define PRINT_ACCEL (0x01) #define PRINT_GYRO (0x02) #define PRINT_QUAT (0x04) #define ACCEL_ON (0x01) #define GYRO_ON (0x02) #define MOTION (0) #define NO_MOTION (1) #define DEFAULT_MPU_HZ (200) #define FLASH_SIZE (512) #define FLASH_MEM_START ((void *)0x1800) #define q30 1073741824.0f short gyro[3], accel[3], sensors; float Roll, Pitch, Yaw; float q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f; static signed char gyro_orientation[9] = {-1, 0, 0, 0, -1, 0, 0, 0, 1}; Imu_t mpu6050 = {0}; Imu_t RegOri_mpu6050 = {0}; // iic转接 #include "bsp_siic.h" static pIICInterface_t siic = &User_sIICDev; uint8_t IICwriteBits(uint8_t addr, uint8_t reg, uint8_t bitStart, uint8_t length, uint8_t data) { uint8_t b; if (siic->read_reg(addr << 1, reg, &b, 1, 200) == IIC_OK) { uint8_t mask = (0xFF << (bitStart + 1)) | (0xFF >> ((8 - bitStart) + length - 1)); data <<= (8 - length); data >>= (7 - bitStart); b &= mask; b |= data; return siic->write_reg(addr << 1, reg, &b, 1, 200); } return 1; } uint8_t IICwriteBit(uint8_t dev, uint8_t reg, uint8_t bitNum, uint8_t data) { uint8_t b; siic->read_reg(dev << 1, reg, &b, 1, 200); b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); return siic->write_reg(dev << 1, reg, &b, 1, 200); } uint8_t IICreadBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t *data) { return siic->read_reg(dev << 1, reg, data, length, 200); } int i2cRead(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf) { return siic->read_reg(addr << 1, reg, buf, len, 200); } unsigned char I2C_ReadOneByte(unsigned char I2C_Addr, unsigned char addr) { uint8_t b = 0; siic->read_reg(I2C_Addr << 1, addr, &b, 1, 200); return b; } static unsigned short inv_row_2_scale(const signed char *row) { unsigned short b; if (row[0] > 0) b = 0; else if (row[0] < 0) b = 4; else if (row[1] > 0) b = 1; else if (row[1] < 0) b = 5; else if (row[2] > 0) b = 2; else if (row[2] < 0) b = 6; else b = 7; // error return b; } static unsigned short inv_orientation_matrix_to_scalar(const signed char *mtx) { unsigned short scalar; scalar = inv_row_2_scale(mtx); scalar |= inv_row_2_scale(mtx + 3) << 3; scalar |= inv_row_2_scale(mtx + 6) << 6; return scalar; } static void run_self_test(void) { int result; long gyro[3], accel[3]; result = mpu_run_self_test(gyro, accel); if (result == 0x7) { /* Test passed. We can trust the gyro data here, so let's push it down * to the DMP. */ float sens; unsigned short accel_sens; mpu_get_gyro_sens(&sens); gyro[0] = (long)(gyro[0] * sens); gyro[1] = (long)(gyro[1] * sens); gyro[2] = (long)(gyro[2] * sens); dmp_set_gyro_bias(gyro); mpu_get_accel_sens(&accel_sens); accel[0] *= accel_sens; accel[1] *= accel_sens; accel[2] *= accel_sens; dmp_set_accel_bias(accel); // printf("setting bias succesfully ......\r\n"); } } uint8_t buffer[14]; int16_t MPU6050_FIFO[6][11]; int16_t Gx_offset = 0, Gy_offset = 0, Gz_offset = 0; /************************************************************************** Function: The new ADC data is updated to FIFO array for filtering Input : ax,ay,az:x,y, z-axis acceleration data;gx,gy,gz:x. Y, z-axis angular acceleration data Output : none 函数功能:将新的ADC数据更新到 FIFO数组,进行滤波处理 入口参数:ax,ay,az:x,y,z轴加速度数据;gx,gy,gz:x,y,z轴角加速度数据 返回 值:无 **************************************************************************/ void MPU6050_newValues(int16_t ax, int16_t ay, int16_t az, int16_t gx, int16_t gy, int16_t gz) { unsigned char i; int32_t sum = 0; for (i = 1; i < 10; i++) { // FIFO 操作 MPU6050_FIFO[0][i - 1] = MPU6050_FIFO[0][i]; MPU6050_FIFO[1][i - 1] = MPU6050_FIFO[1][i]; MPU6050_FIFO[2][i - 1] = MPU6050_FIFO[2][i]; MPU6050_FIFO[3][i - 1] = MPU6050_FIFO[3][i]; MPU6050_FIFO[4][i - 1] = MPU6050_FIFO[4][i]; MPU6050_FIFO[5][i - 1] = MPU6050_FIFO[5][i]; } MPU6050_FIFO[0][9] = ax; // 将新的数据放置到 数据的最后面 MPU6050_FIFO[1][9] = ay; MPU6050_FIFO[2][9] = az; MPU6050_FIFO[3][9] = gx; MPU6050_FIFO[4][9] = gy; MPU6050_FIFO[5][9] = gz; sum = 0; for (i = 0; i < 10; i++) { // 求当前数组的合,再取平均值 sum += MPU6050_FIFO[0][i]; } MPU6050_FIFO[0][10] = sum / 10; sum = 0; for (i = 0; i < 10; i++) { sum += MPU6050_FIFO[1][i]; } MPU6050_FIFO[1][10] = sum / 10; sum = 0; for (i = 0; i < 10; i++) { sum += MPU6050_FIFO[2][i]; } MPU6050_FIFO[2][10] = sum / 10; sum = 0; for (i = 0; i < 10; i++) { sum += MPU6050_FIFO[3][i]; } MPU6050_FIFO[3][10] = sum / 10; sum = 0; for (i = 0; i < 10; i++) { sum += MPU6050_FIFO[4][i]; } MPU6050_FIFO[4][10] = sum / 10; sum = 0; for (i = 0; i < 10; i++) { sum += MPU6050_FIFO[5][i]; } MPU6050_FIFO[5][10] = sum / 10; } /************************************************************************** Function: Setting the clock source of mpu6050 Input : source:Clock source number Output : none 函数功能:设置 MPU6050 的时钟源 入口参数:source:时钟源编号 返回 值:无 * CLK_SEL | Clock Source * --------+-------------------------------------- * 0 | Internal oscillator * 1 | PLL with X Gyro reference * 2 | PLL with Y Gyro reference * 3 | PLL with Z Gyro reference * 4 | PLL with external 32.768kHz reference * 5 | PLL with external 19.2MHz reference * 6 | Reserved * 7 | Stops the clock and keeps the timing generator in reset **************************************************************************/ void MPU6050_setClockSource(uint8_t source) { IICwriteBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source); } /** Set full-scale gyroscope range. * @param range New full-scale gyroscope range value * @see getFullScaleRange() * @see MPU6050_GYRO_FS_250 * @see MPU6050_RA_GYRO_CONFIG * @see MPU6050_GCONFIG_FS_SEL_BIT * @see MPU6050_GCONFIG_FS_SEL_LENGTH */ void MPU6050_setFullScaleGyroRange(uint8_t range) { IICwriteBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range); } /************************************************************************** Function: Setting the maximum range of mpu6050 accelerometer Input : range:Acceleration maximum range number Output : none 函数功能:设置 MPU6050 加速度计的最大量程 入口参数:range:加速度最大量程编号 返回 值:无 **************************************************************************/ // #define MPU6050_ACCEL_FS_2 0x00 //===最大量程+-2G // #define MPU6050_ACCEL_FS_4 0x01 //===最大量程+-4G // #define MPU6050_ACCEL_FS_8 0x02 //===最大量程+-8G // #define MPU6050_ACCEL_FS_16 0x03 //===最大量程+-16G void MPU6050_setFullScaleAccelRange(uint8_t range) { IICwriteBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range); } /************************************************************************** Function: Set mpu6050 to sleep mode or not Input : enable:1,sleep;0,work; Output : none 函数功能:设置 MPU6050 是否进入睡眠模式 入口参数:enable:1,睡觉;0,工作; 返回 值:无 **************************************************************************/ void MPU6050_setSleepEnabled(uint8_t enabled) { IICwriteBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled); } /************************************************************************** Function: Read identity Input : none Output : 0x68 函数功能:读取 MPU6050 WHO_AM_I 标识 入口参数:无 返回 值:0x68 **************************************************************************/ uint8_t MPU6050_getDeviceID(void) { IICreadBytes(devAddr, MPU6050_RA_WHO_AM_I, 1, buffer); return buffer[0]; } /************************************************************************** Function: Check whether mpu6050 is connected Input : none Output : 1:Connected;0:Not connected 函数功能:检测MPU6050 是否已经连接 入口参数:无 返回 值:1:已连接;0:未连接 **************************************************************************/ uint8_t MPU6050_testConnection(void) { if (MPU6050_getDeviceID() == 0x68) // 0b01101000; return 1; else return 0; } /************************************************************************** Function: Setting whether mpu6050 is the host of aux I2C cable Input : enable:1,yes;0;not Output : none 函数功能:设置 MPU6050 是否为AUX I2C线的主机 入口参数:enable:1,是;0:否 返回 值:无 **************************************************************************/ void MPU6050_setI2CMasterModeEnabled(uint8_t enabled) { IICwriteBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled); } /************************************************************************** Function: Setting whether mpu6050 is the host of aux I2C cable Input : enable:1,yes;0;not Output : none 函数功能:设置 MPU6050 是否为AUX I2C线的主机 入口参数:enable:1,是;0:否 返回 值:无 **************************************************************************/ void MPU6050_setI2CBypassEnabled(uint8_t enabled) { IICwriteBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled); } /************************************************************************** Function: initialization Mpu6050 to enter the available state Input : none Output : none 函数功能:初始化 MPU6050 以进入可用状态 入口参数:无 返回 值:无 **************************************************************************/ void MPU6050_initialize(void) { // 未识别陀螺仪,复位 if (MPU6050_getDeviceID() != 0x68) DL_SYSCTL_resetDevice(DL_SYSCTL_RESET_POR); MPU6050_setClockSource(MPU6050_CLOCK_PLL_YGYRO); // 设置时钟 MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_2000); // 陀螺仪量程设置 MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2); // 加速度度最大量程 +-2G MPU6050_setSleepEnabled(0); // 进入工作状态 MPU6050_setI2CMasterModeEnabled(0); // 不让MPU6050 控制AUXI2C MPU6050_setI2CBypassEnabled(0); // 主控制器的I2C与 MPU6050的AUXI2C 直通关闭 } /************************************************************************** Function: Initialization of DMP in mpu6050 Input : none Output : none 函数功能:MPU6050内置DMP的初始化 入口参数:无 返回 值:无 **************************************************************************/ void DMP_Init(void) { uint8_t resetflag = 0; uint8_t temp[1] = {0}; i2cRead(0x68, 0x75, 1, temp); printf("mpu_set_sensor complete ......\r\n"); if (temp[0] != 0x68) DL_SYSCTL_resetDevice(DL_SYSCTL_RESET_POR); if (!mpu_init()) { if (!mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL)) printf("mpu_set_sensor complete ......\r\n"); else resetflag = 1; if (!mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL)) printf("mpu_configure_fifo complete ......\r\n"); else resetflag = 1; if (!mpu_set_sample_rate(DEFAULT_MPU_HZ)) printf("mpu_set_sample_rate complete ......\r\n"); else resetflag = 1; if (!dmp_load_motion_driver_firmware()) printf("dmp_load_motion_driver_firmware complete ......\r\n"); else resetflag = 1; if (!dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation))) printf("dmp_set_orientation complete ......\r\n"); else resetflag = 1; if (!dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT | DMP_FEATURE_TAP | DMP_FEATURE_ANDROID_ORIENT | DMP_FEATURE_SEND_RAW_ACCEL | DMP_FEATURE_SEND_CAL_GYRO | DMP_FEATURE_GYRO_CAL)) printf("dmp_enable_feature complete ......\r\n"); else resetflag = 1; if (!dmp_set_fifo_rate(DEFAULT_MPU_HZ)) printf("dmp_set_fifo_rate complete ......\r\n"); else resetflag = 1; run_self_test(); if (!mpu_set_dmp_state(1)) printf("mpu_set_dmp_state complete ......\r\n"); } else { DL_SYSCTL_resetDevice(DL_SYSCTL_RESET_POR); } if (resetflag) { mpu6050_i2c_sda_unlock(); DL_SYSCTL_resetDevice(DL_SYSCTL_RESET_POR); } } /************************************************************************** Function: Read the attitude information of DMP in mpu6050 Input : none Output : none 函数功能:读取MPU6050内置DMP的姿态信息 入口参数:无 返回 值:无 **************************************************************************/ void Read_DMP(void) { unsigned long sensor_timestamp; unsigned char more; long quat[4]; dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors, &more); // 读取DMP数据 if (sensors & INV_WXYZ_QUAT) { q0 = quat[0] / q30; q1 = quat[1] / q30; q2 = quat[2] / q30; q3 = quat[3] / q30; // 四元数 Roll = asin(-2 * q1 * q3 + 2 * q0 * q2) * 57.3; // 计算出横滚角 Pitch = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2 * q2 + 1) * 57.3; // 计算出俯仰角 Yaw = atan2(2 * (q1 * q2 + q0 * q3), q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3) * 57.3; // 计算出偏航角 } } /************************************************************************** Function: Read mpu6050 built-in temperature sensor data Input : none Output : Centigrade temperature 函数功能:读取MPU6050内置温度传感器数据 入口参数:无 返回 值:摄氏温度 **************************************************************************/ int Read_Temperature(void) { float Temp; Temp = (I2C_ReadOneByte(devAddr, MPU6050_RA_TEMP_OUT_H) << 8) + I2C_ReadOneByte(devAddr, MPU6050_RA_TEMP_OUT_L); if (Temp > 32768) Temp -= 65536; // 数据类型转换 Temp = (36.53 + Temp / 340) * 10; // 温度放大十倍存放 return (int)Temp; } //------------------End of File----------------------------
07-22
/** ***************************************************************** * @文件名 task.c * @作者 张法军 * @版本 V3.01 * @日期 2025年10* @描述 UCOSII系统任务调度处理源文件 *******************************************************************/ #include "sys.h" #include "stdio.h" #include "usart.h" #include "error_log.h" #include "i2c.h" #include "ipmc_data_handle.h" #include "includes.h" #include <stdbool.h> #include "task.h" #include <string.h> #include "log.h" #include "handle_task_method.h" #include "task.h" #include "stm32f10x.h" #include "slot_address_map.h" /////////////////////////////////////变量定义////////////////////////////////////////////////////////////// #if USE_I2C1 volatile int enable_I2C1 = 1; #else volatile int enable_I2C1 = 0; #endif #if USE_I2C2 volatile int enable_I2C2 = 1; #else volatile int enable_I2C2 = 0; #endif u8 frameIndex = 0; unsigned char responseAddress; OS_EVENT *DeviceQueue;// 统一的设备队列 void *DeviceQueueEntries[16]; // 设备管理互斥锁 OS_EVENT *device_mutex; ////////////////////////////////////全局数组定义/////////////////////////////////////////////////////////// //定义发送命令的名称 char* commandsNames[] = {"Send device id", "Send device guid","Send devide sdr1","Send sensor reading1","Send devide sdr2", "Send sensor reading2","Send devide sdr3","Send sensor reading3","Send payload test result", "Send device borad runtime","Send device SN","Send device date","send get fan speed"}; //定义发送缓冲区 uint8_t* buffers[] = {Tx_Id_Buffer,Tx_Guid_Buffer,Tx_Sdr_Buffer_1,Tx_Sensor_Reading_Temperature_Buffer,Tx_Sdr_Buffer_2, Tx_Sensor_Reading_Voltage_Buffer,Tx_Sdr_Buffer_3,Tx_Sensor_Reading_Current_Buffer, Tx_Payload_Test_Result_Buffer,Tx_Runtime_Buffer,Tx_SN_Buffer, Tx_Date_Buffer,Tx_Get_Fan_Buffer }; //定义缓冲区大小 size_t bufferSizes[] = {sizeof(Tx_Id_Buffer), sizeof(Tx_Guid_Buffer), sizeof(Tx_Sdr_Buffer_1),sizeof(Tx_Sensor_Reading_Temperature_Buffer), sizeof(Tx_Sdr_Buffer_2),sizeof(Tx_Sensor_Reading_Voltage_Buffer),sizeof(Tx_Sdr_Buffer_3), sizeof(Tx_Sensor_Reading_Current_Buffer),sizeof(Tx_Payload_Test_Result_Buffer), sizeof(Tx_Runtime_Buffer),sizeof(Tx_SN_Buffer),sizeof(Tx_Date_Buffer),sizeof(Tx_Get_Fan_Buffer) }; char usart1_buffer[50]; //定义从机地址数组 uint8_t slave_addresses[16] = {0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e,0x90,0x92,0x94,0x96,0x98,0x9a,0x9e,0xA0,0xA2}; ////////////////////////////////////////任务控制块定义///////////////////////////////////////////////////// OS_STK CONTROL_CMD_TASK_STK[CONTROL_CMD_TASK_STK_SIZE]; // 定义控制命令任务控制块 #if ENABLE_WATCHDOG OS_STK IWDG_TASK_STK[IWDG_STK_SIZE]; // 定义看门狗任务控制块 #endif #if USE_I2C1 OS_STK CHECK_DEVICES_TASK_STK_A[CHECK_DEVICES_STK_SIZE_A];// 定义设备检测任务控制块IPMB_A OS_STK I2C1_SEND_TASK_STK[I2C_STK_SIZE]; // 定义I2C1发送任务控制块 #endif #if USE_I2C2 OS_STK CHECK_DEVICES_TASK_STK_B[CHECK_DEVICES_STK_SIZE_B];// 定义设备检测任务控制块IPMB_B #endif OS_STK I2C_REV_TASK_STK[I2C_REV_TASK_STK_SIZE]; // 定义I2C接收任务控制块 OS_STK USART2_TX_TASK_STK[USART2_SEND_STK_SIZE]; // 定义串口2发送数据任务控制块 OS_STK USART2_RX_TASK_STK[USART2_REV_STK_SIZE]; // 定义串口2接收数据任务控制块 /////////////////////////////////////////信号量、队列其他定义/////////////////////////////////////////// OS_EVENT *USART_Receive_Complete_Sem; //定义串口接收数据完成信号量 OS_EVENT *I2C_Receive_Complete_Sem; // 定义I2C接收数据完成信号量 OS_EVENT *I2C_Send_Wait_Sem; // 定义I2C发送数据等待信号量 #if USE_I2C1 OS_EVENT *i2c1_sem; // 使用信号量替代互斥锁 #endif #if USE_I2C2 OS_EVENT *i2c2_sem; // 使用信号量替代互斥锁 #endif OS_EVENT *ControlCmdQueue; // 控制命令队列20250927 void *ControlCmdQueueTbl[10]; // 控制命令队列存储空间20250927 static ControlCmdMessage ControlCmdPool[MAX_CONTROL_CMDS];// 添加静态数组 static INT8U ControlCmdIndex = 0; //////////////////////////////////////////////////////////////////////////////////////////////////////////// /********************************************************************* * 函数名称:start_task * 版本标识:v3.00 * 创建人: 张法军 * 创建时间:2024年9月10* 功能描述:UCOSII系统开始任务 * 函数输入:无 * 函数输出:无 **********************************************************************/ void start_task(void *pdata) { u8 err; pdata = pdata; DEBUG_INFO("开始任务初始化..."); OSTimeDlyHMSM(0, 0, 3, 0); init_device_info(); ControlCmdQueue = OSQCreate(&ControlCmdQueueTbl[0], 16); USART_Receive_Complete_Sem = OSSemCreate(0); I2C_Receive_Complete_Sem = OSSemCreate(0); I2C_Send_Wait_Sem = OSSemCreate(1); DeviceQueue = OSQCreate(&DeviceQueueEntries[0], 16); #if USE_I2C1 i2c1_sem = OSSemCreate(1); if (i2c1_sem == NULL) { DEBUG_ERROR("创建i2c1_sem失败"); enable_I2C1 = 0; } else { DEBUG_INFO("创建i2c1_sem成功"); enable_I2C1 = 1; } #endif #if USE_I2C2 i2c2_sem = OSSemCreate(1); if (i2c2_sem == NULL) { DEBUG_ERROR("创建i2c2信号量失败"); enable_I2C2 = 0; } else { DEBUG_INFO("创建i2c2信号量成功"); enable_I2C2 = 1; } #endif device_mutex = OSMutexCreate(0, &err); if (err != OS_ERR_NONE) { DEBUG_ERROR("创建设备互斥锁失败,错误码: %d", err); } // 创建设备检测任务 #if USE_I2C1 OSTaskCreate(TaskCheckDevices_A, (void *)0, &CHECK_DEVICES_TASK_STK_A[CHECK_DEVICES_STK_SIZE_A-1], CHECK_DEVICES_PRIO_A); #endif #if USE_I2C2 OSTaskCreate(TaskCheckDevices_B, (void *)0, &CHECK_DEVICES_TASK_STK_B[CHECK_DEVICES_STK_SIZE_B-1], CHECK_DEVICES_PRIO_B); #endif OSTaskCreate(TaskSendI2C, (void *)0, &I2C1_SEND_TASK_STK[I2C_STK_SIZE-1], SEND_TASK_PRIO); OSTaskCreate(TaskReceiveI2C, (void *)0, &I2C_REV_TASK_STK[I2C_REV_TASK_STK_SIZE-1], I2C_REV_TASK_PRIO); OSTaskCreate(TaskUsart2Send, (void *)0, &USART2_TX_TASK_STK[USART2_SEND_STK_SIZE-1], USART2_SEND_PRIO); OSTaskCreate(USART2_ProcessTask, (void *)0, &USART2_RX_TASK_STK[USART2_REV_STK_SIZE-1], USART2_REV_PRIO); OSTaskCreate(ControlCmdTask, (void *)0, &CONTROL_CMD_TASK_STK[CONTROL_CMD_TASK_STK_SIZE-1], CONTROL_CMD_TASK_PRIO); #if ENABLE_WATCHDOG OSTaskCreate(TaskIWDG, (void *)0, &IWDG_TASK_STK[IWDG_STK_SIZE-1], IWDG_PRIO); #endif DEBUG_INFO("所有任务创建完成,系统启动成功"); OSTaskSuspend(START_TASK_PRIO); } /********************************************************************* * 函数名称:ControlCmdTask * 版本标识:v3.00 * 创建人: 张法军 * 创建时间:2025年9月17日 * 功能描述:处理控制命令的最高优先级任务 * 函数输入:无 * 函数输出:无 **********************************************************************/ void ControlCmdTask(void *pdata){ INT8U err; ControlCmdMessage *cmd_msg; bool send_success; while(1) { cmd_msg = (ControlCmdMessage *)OSQPend(ControlCmdQueue, 0, &err); if(err == OS_ERR_NONE) { DEBUG_PRINT("接收到控制命令,设备地址: 0x%02X", cmd_msg->device_address); bool critical_error = false; // 改为局部变量,每个命令独立 DeviceInfo info; if (get_device_info(cmd_msg->device_address, &info)) { // 使用设备的优先总线发送控制命令 if (info.preferred_bus == BUS_I2C1 && enable_I2C1) { send_success = send_via_i2c1(cmd_msg->device_address, cmd_msg->command, cmd_msg->length, &critical_error); if (!send_success && enable_I2C2 && !critical_error) { // 只有在没有关键错误时才尝试备用总线 send_success = send_via_i2c2(cmd_msg->device_address, cmd_msg->command, cmd_msg->length, &critical_error); } } else if (info.preferred_bus == BUS_I2C2 && enable_I2C2) { send_success = send_via_i2c2(cmd_msg->device_address, cmd_msg->command, cmd_msg->length, &critical_error); if (!send_success && enable_I2C1 && !critical_error) { send_success = send_via_i2c1(cmd_msg->device_address, cmd_msg->command, cmd_msg->length, &critical_error); } } } else { // 如果没有设备信息,按原逻辑尝试 send_success = send_via_i2c1(cmd_msg->device_address, cmd_msg->command, cmd_msg->length, &critical_error); if (!send_success && !critical_error) { send_success = send_via_i2c2(cmd_msg->device_address, cmd_msg->command, cmd_msg->length, &critical_error); } } #if ENABLE_ERROR_LOGGING if(send_success) { DEBUG_PRINT("控制命令发送成功"); } else { if (critical_error) { DEBUG_ERROR("控制命令发送失败 - 关键错误,跳过设备"); } else { DEBUG_ERROR("控制命令发送失败"); } } #endif memset(cmd_msg->command, 0, cmd_msg->length); } } } /********************************************************************* * 函数名称:TaskSendI2C * 版本标识:v3.04 * 创建人: 张法军 * 创建时间:2025年10月12* 功能描述:I2C发送任务 - 优化错误处理,避免过度跳过设备 * 函数输入:无 * 函数输出:无 **********************************************************************/ void TaskSendI2C(void *pdata){ uintptr_t device_msg; u8 err; while (1) { device_msg = (uintptr_t)OSQPend(DeviceQueue, 0, &err); if (err == OS_ERR_NONE) { uint8_t deviceAddress = (uintptr_t)device_msg; DeviceInfo info; if (!get_device_info(deviceAddress, &info)) { DEBUG_ERROR("未找到设备 0x%02X 的信息", deviceAddress); continue; } // 检查设备是否应该被处理 if (!should_process_device(deviceAddress)) { DEBUG_PRINT("设备 0x%02X 不可用、不在线或不需要处理,跳过", deviceAddress); continue; } DEBUG_PRINT("开始处理设备 0x%02X,优先总线: %s", deviceAddress, info.preferred_bus == BUS_I2C1 ? "I2C1" : "I2C2"); /* 根据设备地址确定要发送的帧数 */ int totalFrames; if (deviceAddress == 0xA2) { totalFrames = sizeof(buffers) / sizeof(buffers[0]); DEBUG_PRINT("A2设备,发送所有%d帧数据", totalFrames); } else { totalFrames = (sizeof(buffers) / sizeof(buffers[0])) - 1; DEBUG_PRINT("非A2设备,发送%d帧数据", totalFrames); } OSSemPend(I2C_Send_Wait_Sem, 0, &err); if (err == OS_ERR_NONE) { responseAddress = deviceAddress; bool overall_success = true; bool skip_device = false; for (frameIndex = 0; frameIndex < totalFrames && !skip_device; frameIndex++) { handle_tx_chmc_data(); bool send_success = false; bool use_alternative_bus = false; bool critical_error = false; // 根据优先总线选择发送策略 if (info.preferred_bus == BUS_I2C1 && enable_I2C1) { send_success = send_via_i2c1(deviceAddress, buffers[frameIndex], bufferSizes[frameIndex], &critical_error); if (!send_success && enable_I2C2 && !critical_error) { DEBUG_PRINT("I2C1发送失败,尝试I2C2"); send_success = send_via_i2c2(deviceAddress, buffers[frameIndex], bufferSizes[frameIndex], &critical_error); use_alternative_bus = true; } } else if (info.preferred_bus == BUS_I2C2 && enable_I2C2) { send_success = send_via_i2c2(deviceAddress, buffers[frameIndex], bufferSizes[frameIndex], &critical_error); if (!send_success && enable_I2C1 && !critical_error) { DEBUG_PRINT("I2C2发送失败,尝试I2C1"); send_success = send_via_i2c1(deviceAddress, buffers[frameIndex], bufferSizes[frameIndex], &critical_error); use_alternative_bus = true; } } // 检查关键错误码,需要跳过设备 if (critical_error) { DEBUG_ERROR("设备 0x%02X 发生关键错误,错误码: %d,跳过设备", deviceAddress, I2CErrorCode); mark_device_unavailable(deviceAddress); skip_device = true; overall_success = false; break; // 跳出帧循环 } if (send_success) { DEBUG_PRINT("发送成功: %s", commandsNames[frameIndex]); if (use_alternative_bus) { BusType new_preferred_bus = (info.preferred_bus == BUS_I2C1) ? BUS_I2C2 : BUS_I2C1; update_device_preferred_bus(deviceAddress, new_preferred_bus); } } else { DEBUG_ERROR("发送失败: %s", commandsNames[frameIndex]); overall_success = false; // 普通发送失败继续尝试下一帧 break; } OSSemPost(I2C_Receive_Complete_Sem); OSTimeDlyHMSM(0, 0, 0, 100); OSSemPost(I2C_Send_Wait_Sem); } // OSSemPost(I2C_Send_Wait_Sem); // 处理设备完成状态 if (skip_device) { // 设备已被标记为不可用 DEBUG_ERROR("===========================设备处理跳过: 0x%02X===========================", deviceAddress); } else if (overall_success) { mark_device_processed(deviceAddress); DEBUG_INFO("===========================设备处理完成: 0x%02X===========================", deviceAddress); } else { mark_device_retry(deviceAddress); DEBUG_ERROR("===========================设备处理失败: 0x%02X===========================", deviceAddress); } } else { DEBUG_ERROR("获取发送等待信号量失败"); mark_device_retry(deviceAddress); } } else { DEBUG_ERROR("队列等待错误"); OSTimeDlyHMSM(0, 0, 1, 0); } } } /********************************************************************* * 函数名称:TaskCheckDevices_A * 版本标识:v3.00 * 创建人: 张法军 * 创建时间:2024年9月10* 功能描述:IPMB_A实现设备在线检测任务 * 函数输入:无 * 函数输出:无 **********************************************************************/ #if USE_I2C1 void TaskCheckDevices_A(void *pdata) { u8 err; OS_CPU_SR cpu_sr = 0; const int MAX_RETRIES = 3; DEBUG_INFO("IPMB_A设备检测任务开始运行"); while (1) { for (int deviceIndex = 0; deviceIndex < sizeof(slave_addresses) / sizeof(slave_addresses[0]); deviceIndex++) { uint8_t deviceAddress = slave_addresses[deviceIndex]; if(enable_I2C1) { bool isOnlineI2C1 = false; int retry = 0; while (!isOnlineI2C1 && retry < MAX_RETRIES) { OSSemPend(i2c1_sem, 0, &err); if (err != OS_ERR_NONE) { break; } OS_ENTER_CRITICAL(); int status = I2C_CheckDevice(I2C1, deviceAddress); OS_EXIT_CRITICAL(); if (status == 1) { isOnlineI2C1 = true; update_device_status(deviceAddress, BUS_I2C1, true); #if DEBUG_LEVEL >= 2 DEBUG_PRINT("设备在线(IPMB_A): 0x%02X", deviceAddress); #endif } else { retry++; update_device_status(deviceAddress, BUS_I2C1, false); } OSSemPost(i2c1_sem); } if (!isOnlineI2C1 && retry < MAX_RETRIES) { OSTimeDlyHMSM(0, 0, 0, 10); } } } OSTimeDlyHMSM(0, 0, 5, 0); } } #endif #if USE_I2C2 void TaskCheckDevices_B(void *pdata) { u8 err; OS_CPU_SR cpu_sr = 0; const int MAX_RETRIES = 3; DEBUG_INFO("IPMB_B设备检测任务开始运行"); while (1) { for (int deviceIndex = 0; deviceIndex < sizeof(slave_addresses) / sizeof(slave_addresses[0]); deviceIndex++) { uint8_t deviceAddress = slave_addresses[deviceIndex]; if (enable_I2C2) { bool isOnlineI2C2 = false; int retry = 0; while (!isOnlineI2C2 && retry < MAX_RETRIES) { OSSemPend(i2c2_sem, 0, &err); if (err != OS_ERR_NONE) { break; } OS_ENTER_CRITICAL(); int status = I2C_CheckDevice(I2C2, deviceAddress); OS_EXIT_CRITICAL(); if (status == 1) { isOnlineI2C2 = true; update_device_status(deviceAddress, BUS_I2C2, true);// 使用统一的设备状态更新函数 #if DEBUG_LEVEL >= 2 DEBUG_PRINT("设备在线(IPMB_B): 0x%02X", deviceAddress); #endif } else { retry++; update_device_status(deviceAddress, BUS_I2C2, false); } OSSemPost(i2c2_sem); } if (!isOnlineI2C2 && retry < MAX_RETRIES) { OSTimeDlyHMSM(0, 0, 0, 10); } } } OSTimeDlyHMSM(0, 0, 5, 0); } } #endif /********************************************************************* * 函数名称:TaskReceiveI2C * 版本标识:v3.00 * 创建人: 张法军 * 创建时间:2024年9月10* 功能描述:接收I2C数据任务 * 函数输入:无 * 函数输出:无 * 修改内容1: * 修改人1: * 修改时间1: **********************************************************************/ void TaskReceiveI2C(void *pdata){ OS_CPU_SR cpu_sr = 0; u8 err; while (1) { OSSemPend(I2C_Receive_Complete_Sem, 0, &err); // 等待数据就绪 if(err == OS_ERR_NONE) { if(rx_complete_flag) { rx_complete_flag = 0; // 清除接收完成标志 OS_ENTER_CRITICAL();//进入临界区 handle_rx_ipmc_data(); OS_EXIT_CRITICAL();//退出临界区 memset(I2C_Buffer_Rx,0,sizeof(I2C_Buffer_Rx)); frameLength = 0; // 重置索引 OSSemPost(I2C_Send_Wait_Sem); // 允许发送任务继续 } } else { clear_rx_i2c_buffer(); // 可能需要清空缓冲区或重置某些状态 DEBUG_ERROR("等待接收I2C数据超时!"); } } } /********************************************************************* * 函数名称:TaskUsart2RevAndSend * 版本标识:v3.00 * 创建人: 张法军 * 创建时间:2024年10* 功能描述:CHMC数据处理任务 * 函数输入:无 * 函数输出:无 * 修改内容1: * 修改人1: * 修改时间1: **********************************************************************/ void TaskUsart2Send(void *pdata){ while(1) { usart_single_count ++; usart_health_count ++; usart_fan_count ++; GPIO_SetBits(GPIOB,GPIO_Pin_9);//警告灯 OSTimeDlyHMSM(0,0,0,100); GPIO_ResetBits(GPIOB,GPIO_Pin_9); chmc_data_to_usart();//调用chmc数据获取复制函数 usart2_send_data();//调用串口组帧函数 USART2_SendNByte(USART2_SEND_SINGLE_BUFFER,sizeof(USART2_SEND_SINGLE_BUFFER)); OSTimeDlyHMSM(0,0,0,100); USART2_SendNByte(USART2_SEND_HEALTH_BUFFER,sizeof(USART2_SEND_HEALTH_BUFFER)); OSTimeDlyHMSM(0,0,0,100); USART2_SendNByte(USART2_SEND_FAN_BUFFER,sizeof(USART2_SEND_FAN_BUFFER)); OSTimeDlyHMSM(0,0,0,100);//根据实际需求调整时间,释放CPU } } /********************************************************************* * 函数名称:USART2_ProcessTask * 版本标识:v3.00 * 创建人: 张法军 * 创建时间:2025年9月17日 * 功能描述:在任务中处理USART2数据 * 函数输入:无 * 函数输出:无 * 修改内容1: * 修改人1: * 修改时间1: **********************************************************************/ void USART2_ProcessTask(void *pdata) { INT8U err; uint8_t device_addr; ControlCmdMessage *cmd_msg; while(1) { // 等待USART2数据就绪信号量 OSSemPend(USART_Receive_Complete_Sem, 0, &err); if(err == OS_ERR_NONE && usart2_frame_ready) { // 使用映射表查找设备地址 device_addr = find_device_address_by_slot(rx_usart2_data.slot); if (device_addr != 0) { cmd_msg = AllocateControlCmd(); // 分配消息内存 if (cmd_msg != NULL) { DEBUG_PRINT("接收槽位号:0x%02X",rx_usart2_data.slot); if(rx_usart2_data.slot == 0x11) { responseAddress = device_addr; // 响应地址 fanLevel = rx_usart2_data.command;// 风扇挡位控制命令 makeSendData(12); // 组帧 cmd_msg->device_address = device_addr; // 地址发送 cmd_msg->length = sizeof(TxSetFanLevel);// 数据帧长度 memcpy(cmd_msg->command, &tx_set_fan_level, cmd_msg->length); memset(&tx_set_fan_level,0,sizeof(TxSetFanLevel)); DEBUG_PRINT("接收风扇挡位:0x%02X",fanLevel); } else if(rx_usart2_data.slot == 0x0e) { chmc_controller_command(rx_usart2_data.command);// CHMC主控payload控制处理 } else { responseAddress = device_addr; // 响应地址 controllerCommand = rx_usart2_data.command;// payload状态控制IPMC状态控制 makeSendData(8); cmd_msg->device_address = device_addr; cmd_msg->length = sizeof(TxFRUActivation); memcpy(cmd_msg->command,&tx_FRU_activation,cmd_msg->length); memset(&tx_FRU_activation,0,sizeof(TxFRUActivation)); DEBUG_PRINT("接收控制命令:0x%02X",controllerCommand); } // 发送到控制命令队列 OSQPost(ControlCmdQueue, (void *)cmd_msg); } } usart2_frame_ready = 0; // 清除标志位 memset(rx_usart_buffer, 0, sizeof(rx_usart_buffer)); } } } /********************************************************************* * 函数名称:TaskIWDG * 版本标识:v3.00 * 创建人: 张法军 * 创建时间:2025年3月 * 功能描述:看门狗任务 * 函数输入:无 * 函数输出:无 **********************************************************************/ #if ENABLE_WATCHDOG void TaskIWDG(void *pdata) { DEBUG_INFO("看门狗任务开始运行"); while(1) { IWDG_ReloadCounter(); OSTimeDlyHMSM(0, 0, 0, 100); } } #endif /********************************************************************* * 函数名称:AllocateControlCmd * 版本标识:v3.00 * 创建人: 张法军 * 创建时间:2025年9月17日 * 功能描述:分配函数 * 函数输入:无 * 函数输出:无 **********************************************************************/ ControlCmdMessage *AllocateControlCmd(void){ if(ControlCmdIndex < MAX_CONTROL_CMDS) { return &ControlCmdPool[ControlCmdIndex++]; } DEBUG_ERROR("控制命令池已满,无法分配新命令"); return NULL; } /** * @brief 通过I2C1发送数据 */ bool send_via_i2c1(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool* critical_error) { u8 err; OS_CPU_SR cpu_sr; bool success = false; int retry_count = 0; *critical_error = false; // 初始化为false while (retry_count < 3 && !success && !(*critical_error)) { OSSemPend(i2c1_sem, 0, &err); if (err == OS_ERR_NONE) { OS_ENTER_CRITICAL(); success = i2c_master_send_buffer_data(I2C1, deviceAddress, buffer, size); OS_EXIT_CRITICAL(); OSSemPost(i2c1_sem); } else { DEBUG_ERROR("获取i2c1信号量失败"); break; } retry_count++; if (!success && retry_count < 3) { DEBUG_PRINT("I2C1发送重试 %d,错误码: %d", retry_count, I2CErrorCode); // 检查是否为关键错误 if (I2CErrorCode == 1 || I2CErrorCode == 2 || I2CErrorCode == 3 || I2CErrorCode == 5 || I2CErrorCode == 6) { *critical_error = true; DEBUG_ERROR("检测到关键错误码 %d,停止重试", I2CErrorCode); break; } } } return success; } /** * @brief 通过I2C2发送数据 */ bool send_via_i2c2(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool *critical_error) { u8 err; OS_CPU_SR cpu_sr; bool success = false; int retry_count = 0; *critical_error = false; // 初始化为false while (retry_count < 3 && !success && !(*critical_error)) { OSSemPend(i2c2_sem, 0, &err); if (err == OS_ERR_NONE) { OS_ENTER_CRITICAL(); success = i2c_master_send_buffer_data(I2C2, deviceAddress, buffer, size); OS_EXIT_CRITICAL(); OSSemPost(i2c2_sem); } else { DEBUG_ERROR("获取i2c2信号量失败"); break; } retry_count++; if (!success && retry_count < 3) { DEBUG_PRINT("I2C2发送重试 %d,错误码: %d", retry_count, I2CErrorCode); // 检查是否为关键错误 if (I2CErrorCode == 1 || I2CErrorCode == 2 || I2CErrorCode == 3 || I2CErrorCode == 5 || I2CErrorCode == 6) { *critical_error = true; DEBUG_ERROR("检测到关键错误码 %d,停止重试", I2CErrorCode); break; } } } return success; } /** * @brief 更新设备优先总线 */ void update_device_preferred_bus(uint8_t address, BusType new_bus) { INT8U err; OSMutexPend(device_mutex, 0, &err); if (err == OS_ERR_NONE) { for (int i = 0; i < MAX_DEVICES; i++) { if (device_info[i].address == address) { device_info[i].preferred_bus = new_bus; DEBUG_PRINT("设备 0x%02X 优先总线更新为: %s", address, new_bus == BUS_I2C1 ? "I2C1" : "I2C2"); break; } } OSMutexPost(device_mutex); } } /** * @brief 初始化设备信息 */ void init_device_info(void) { for (int i = 0; i < MAX_DEVICES; i++) { device_info[i].address = slave_addresses[i]; device_info[i].is_online = false; device_info[i].detected_bus = BUS_NONE; device_info[i].preferred_bus = BUS_I2C1; // 默认优先使用I2C1 device_info[i].last_comm_time = 0; device_info[i].retry_count = 0; device_info[i].needs_processing = false; } } /** * @brief 更新设备状态 */ void update_device_status(uint8_t address, BusType detected_bus, bool is_online) { INT8U err; OSMutexPend(device_mutex, 0, &err); if (err == OS_ERR_NONE) { for (int i = 0; i < MAX_DEVICES; i++) { if (device_info[i].address == address) { bool was_online = device_info[i].is_online; device_info[i].is_online = is_online; device_info[i].detected_bus = detected_bus; device_info[i].last_comm_time = OSTimeGet(); // 如果设备从离线变为在线,重置重试计数设备状态 if (is_online && !was_online) { device_info[i].retry_count = 0; device_info[i].device_status = true; // 重置为可用状态 device_info[i].needs_processing = true; OSQPost(DeviceQueue, (void*)(uintptr_t)address); DEBUG_PRINT("设备 0x%02X 上线,加入处理队列,检测总线: %s", address, detected_bus == BUS_I2C1 ? "I2C1" : "I2C2"); } // 如果设备离线,标记为不需要处理 else if (!is_online) { device_info[i].needs_processing = false; } break; } } OSMutexPost(device_mutex); } } /** * @brief 标记设备处理完成 */ void mark_device_processed(uint8_t address) { INT8U err; OSMutexPend(device_mutex, 0, &err); if (err == OS_ERR_NONE) { for (int i = 0; i < MAX_DEVICES; i++) { if (device_info[i].address == address) { device_info[i].needs_processing = false; device_info[i].retry_count = 0; break; } } OSMutexPost(device_mutex); } } /** * @brief 标记设备需要重试 */ void mark_device_retry(uint8_t address) { INT8U err; OSMutexPend(device_mutex, 0, &err); if (err == OS_ERR_NONE) { for (int i = 0; i < MAX_DEVICES; i++) { if (device_info[i].address == address) { device_info[i].retry_count++; if (device_info[i].retry_count < MAX_RETRY_COUNT) { // 切换优先总线进行重试 device_info[i].preferred_bus = (device_info[i].preferred_bus == BUS_I2C1) ? BUS_I2C2 : BUS_I2C1; device_info[i].needs_processing = true; OSQPost(DeviceQueue, (void*)(uintptr_t)address); DEBUG_PRINT("设备 0x%02X 需要重试 %d/%d,切换优先总线到: %s", address, device_info[i].retry_count, MAX_RETRY_COUNT, device_info[i].preferred_bus == BUS_I2C1 ? "I2C1" : "I2C2"); } else { // 达到最大重试次数,标记设备不可用 mark_device_unavailable(address); DEBUG_ERROR("设备 0x%02X 达到最大重试次数,标记为不可用", address); } break; } } OSMutexPost(device_mutex); } } /** * @brief 获取设备信息 */ bool get_device_info(uint8_t address, DeviceInfo *info) { INT8U err; bool found = false; OSMutexPend(device_mutex, 0, &err); if (err == OS_ERR_NONE) { for (int i = 0; i < MAX_DEVICES; i++) { if (device_info[i].address == address) { *info = device_info[i]; found = true; break; } } OSMutexPost(device_mutex); } return found; } /** * @brief 检查设备是否应该被处理 */ bool should_process_device(uint8_t address) { DeviceInfo info; if (get_device_info(address, &info)) { return info.device_status && info.is_online && info.needs_processing; } return false; } /** * @brief 标记设备为不可用 */ void mark_device_unavailable(uint8_t address) { INT8U err; OSMutexPend(device_mutex, 0, &err); if (err == OS_ERR_NONE) { for (int i = 0; i < MAX_DEVICES; i++) { if (device_info[i].address == address) { device_info[i].device_status = false; // 标记设备不可用 device_info[i].is_online = false; // 标记为离线 device_info[i].needs_processing = false; // 不需要处理 device_info[i].retry_count = 0; // 重置重试计数 DEBUG_PRINT("设备 0x%02X 被标记为不可用,跳过处理", address); break; } } OSMutexPost(device_mutex); } }以上代码为什么没能实现检测设备在线时,向该设备发送数据,如果设备在线,但是向该在线设备发送数据失败时,跳过该设备,继续向下一在线设备发送数据,请根据以上提供的代码,帮我实现以上描述的功能,请给出详细的代码
最新发布
10-17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值