aardio开发上位机学习启用独立域名了: www.htmlayout.cn , 请移步到此处学习!

回复

admin 发起了问题 • 1 人关注 • 0 个回复 • 2029 次浏览 • 2018-01-04 21:31 • 来自相关话题

分享一个利用Cubemx直接生成Coide工程文件的小工具(欢迎提交bug)

super_meters 回复了问题 • 4 人关注 • 2 个回复 • 6326 次浏览 • 2017-10-18 09:17 • 来自相关话题

IAP调试前准备之什么是IAP?协议Ymodem是什么?运行机制是什么

仿如梦境 回复了问题 • 3 人关注 • 1 个回复 • 3762 次浏览 • 2017-10-14 19:01 • 来自相关话题

(自用)aar里面的一些基本功能笔记

admin 发表了文章 • 39 个评论 • 3720 次浏览 • 2017-09-14 13:29 • 来自相关话题

string库中的concat拼接字符串:这个函数提示里面只是显示了两个可用参数,实际应用过程中,可以添加无数个参数,,,都会拼接到一起的.str = string.concat(str,linestr[i],'\r\n',"aaadddggg");这个意思就是把括号里面的四个参数作为字符串拼接到了一起... 查看全部

string库中的concat拼接字符串:

blob.png

这个函数提示里面只是显示了两个可用参数,实际应用过程中,可以添加无数个参数,,,都会拼接到一起的.

str = string.concat(str,linestr[i],'\r\n',"aaadddggg");

这个意思就是把括号里面的四个参数作为字符串拼接到了一起...

(自用)AAR里一些好玩的功能

admin 发表了文章 • 65 个评论 • 7939 次浏览 • 2017-08-23 12:39 • 来自相关话题

最近aar作者Jacen He更新了一些新库:二维码和条形码的识别库Zbar//生成测试二维码
import qrencode.bitmap;
var qrBmp = qrencode.bitmap("http://www.stm32cube.com/#Stm32cube中文网" );
qrBmp.copyBitmap(100).save("/qrcode.jpg",80) 
 
//识别二维码    
import zbar;
import soImage; //此扩展库要使用最新版

var img = soImage();
img.load("/qrcode.jpg");//加载二维码图像
img.grayScale();
    
scanner = zbar.scanner();
scanner.config('qrcode.enable');//可省略

import console;
scanner.scan(img.getData(),img.getWidth(),img.getHeight(),function(typeName,data){
     console.log(typeName,data)
    })
     
    
console.pause();二维码和条形码的应用挺广泛的,这个库实用性很大,先前也实现过类似功能,不过用的调用js的方法. 查看全部

最近aar作者Jacen He更新了一些新库:

二维码和条形码的识别库Zbar

//生成测试二维码
import qrencode.bitmap;
var qrBmp = qrencode.bitmap("http://www.stm32cube.com/#Stm32cube中文网" );
qrBmp.copyBitmap(100).save("/qrcode.jpg",80) 
 
//识别二维码    
import zbar;
import soImage; //此扩展库要使用最新版

var img = soImage();
img.load("/qrcode.jpg");//加载二维码图像
img.grayScale();
    
scanner = zbar.scanner();
scanner.config('qrcode.enable');//可省略

import console;
scanner.scan(img.getData(),img.getWidth(),img.getHeight(),function(typeName,data){
     console.log(typeName,data)
    })
     
    
console.pause();

blob.png

二维码和条形码的应用挺广泛的,这个库实用性很大,先前也实现过类似功能,不过用的调用js的方法.

(转)设置stm32芯片的读保护来防止恶意读取代码的方法

admin 发表了文章 • 0 个评论 • 12854 次浏览 • 2017-08-08 20:12 • 来自相关话题

现在的MCU大部分都会提供读保护和写保护的功能。读保护:保护保存在MCU上的执行代码不会被调试/下载工具拷贝出来。STM32 读保护有三个等级 L0 L1 L2  L0 是没有保护,可以随意读出来的,一般调试过程中选择。在L0 状态可以设置成L1 或者L2,修改完成不会擦除芯片已有的代码;  L1 是可恢复读保护,L1-->L0状态,,会自动擦除已有的程序。L1->L2,这个设置还没有试过,(正常理解是不擦除);  L2 是不可恢复读保护,此状态下,不可恢复到其他的状态,同时芯片里的程序不能再升级 类似OTP了;  这个主要是保护代码不会被其他人恶意拷贝,保护原作者的权益。写保护: 保护存在MCU上的代码 不会被异常修改。正常的代码更新流程需要先失能对应的保护位,更新完成再次恢复之前的保护位。这个主要是保护程序正常运行的时候,不会被异常更改。如图的STM32 ST-LINK UNILITY 工具上的读写保护和一些用户设置,包括在调试的停时 看门狗是否继续计数等设置本文转自:http://www.stmcu.org/module/fo ... .html 我们利用这个读保护特性可以在程序中自由的上锁和解锁我们不需要设置什么按键检测,我们程序中有串口或者usb,spi等等通信的话,可以利用这个通信指令来解锁.我们在while之前加载读保护代码:int main(void)
{
    ....
      
    if(FLASH_GetReadOutProtectionStatus() != SET)
    {
        //FLASH_Unlock();不解锁FALSH也可设置读保护???
        FLASH_ReadOutProtection(ENABLE);   
    }
    ......
    while(1)
    {
       .....
     }
} 然后我们可以在通信程序里面进行指令解析然后,解锁读保护if(FLASH_GetReadOutProtectionStatus() != RESET)
{
FLASH_Unlock();
FLASH_ReadOutProtection(DISABLE);
}这种读保护操作应该是最简单的代码保护方式了吧?..... 查看全部

现在的MCU大部分都会提供读保护和写保护的功能。
读保护:保护保存在MCU上的执行代码不会被调试/下载工具拷贝出来。

STM32 读保护有三个等级 L0 L1 L2
 L0 是没有保护,可以随意读出来的,一般调试过程中选择。在L0 状态可以设置成L1 或者L2,修改完成不会擦除芯片已有的代码;
 L1 是可恢复读保护,L1-->L0状态,,会自动擦除已有的程序。L1->L2,这个设置还没有试过,(正常理解是不擦除);
 L2 是不可恢复读保护,此状态下,不可恢复到其他的状态,同时芯片里的程序不能再升级 类似OTP了
 这个主要是保护代码不会被其他人恶意拷贝,保护原作者的权益。

写保护: 保护存在MCU上的代码 不会被异常修改。

正常的代码更新流程需要先失能对应的保护位,更新完成再次恢复之前的保护位。
这个主要是保护程序正常运行的时候,不会被异常更改。
如图的STM32 ST-LINK UNILITY 工具上的读写保护和一些用户设置,包括在调试的停时 看门狗是否继续计数等设置

213322bzprzlmxxpzk2pkz.png

本文转自:http://www.stmcu.org/module/fo ... .html

 

我们利用这个读保护特性可以在程序中自由的上锁和解锁

我们不需要设置什么按键检测,我们程序中有串口或者usb,spi等等通信的话,

可以利用这个通信指令来解锁.

我们在while之前加载读保护代码:

int main(void)
{
    ....
      
    if(FLASH_GetReadOutProtectionStatus() != SET)
    {
        //FLASH_Unlock();不解锁FALSH也可设置读保护???
        FLASH_ReadOutProtection(ENABLE);   
    }
    ......
    while(1)
    {
       .....
     }
}

 然后我们可以在通信程序里面进行指令解析然后,解锁读保护

if(FLASH_GetReadOutProtectionStatus() != RESET)
{
FLASH_Unlock();
FLASH_ReadOutProtection(DISABLE);
}

这种读保护操作应该是最简单的代码保护方式了吧?.....

(转)aardio字符串模式匹配快速入门

回复

admin 回复了问题 • 2 人关注 • 9 个回复 • 2997 次浏览 • 2017-08-05 01:01 • 来自相关话题

(已弃)利用串口来模拟spi发送一定数量的上升沿脉冲

回复

admin 回复了问题 • 1 人关注 • 1 个回复 • 2629 次浏览 • 2017-08-02 13:05 • 来自相关话题

Aardio学习笔记4

admin 发表了文章 • 11 个评论 • 3705 次浏览 • 2017-07-17 13:08 • 来自相关话题

还是分析Gcode代码用的,先前是直接循环获取一行的数据然后解析显示到listbox中,现在需要点击任意一行然后进行解析测试,如果没有选中任意一行那么就继续循环解析:listbox中有这么个函数:win.ui.ctrl.listbox() = 列表框\n!listbox.
!listbox.cls = 设计时类名
!listbox.className = 运行时类名
!listbox.clear() = 清除列表框所有内容
!listbox.delete() = 删除当前选中项
!listbox.delete(__) = 删除指定项
!listbox.getItemText(__/*项索引*/) = 获取指定项文本
!listbox.getItemRect(__/*项索引*/) = 获取指定项区块位置\n返回::RECT() 结构体
!listbox.getAt(x,y) = 返回指定客户区坐标所在的项索引.
!listbox.add(__/*请输入文本*/) = 添加列表项到尾部
!listbox.add(__/*请输入文本*/,-1) = 添加列表项到尾部
!listbox.add(__/*请输入文本*/,1) = 添加列表项到头部
!listbox.selIndex = 获取或设置列表框当前选中项\n仅在单选模式下有效,多选模式下请使用 getSelected() setSelected() 函数
!listbox.selText = 获取当前选项的文本\n或根据指定的文本查找并改变选项对于这些理解的不是很深,所以需要一步步实践下:姑且会用到mainForm.listbox.selIndex, mainForm.listbox.selText于是在界面中增加一个按钮,用来显示哪个被点选了...console.log(mainForm.listbox.selIndex,mainForm.listbox.selText);blob.png实现上面的完整代码如下:import win.ui;/*DSG{{*/mainForm = win.form(text="aardio form";right=561;bottom=654)mainForm.add(Motion_file={cls="listbox";left=373;top=10;right=552;bottom=530;edge=1;items={};z=2};button={cls="button";text="加载";left=16;top=542;right=173;bottom=591;z=3};button2={cls="button";text="转换";left=197;top=541;right=551;bottom=590;z=4};button3={cls="button";text="获取谁被点选了";left=20;top=598;right=177;bottom=647;z=5};listbox={cls="listbox";left=11;top=9;right=361;bottom=529;edge=1;items={};vscroll=1;z=1})/*}}*/import console;console.open()mainForm.button3.oncommand = function(id,event){ //mainForm.msgbox( mainForm.button3.text ); console.log(mainForm.listbox.selIndex,mainForm.listbox.selText);}mainForm.button.oncommand = function(id,event){ //mainForm.msgbox( mainForm.button.text ); var filecontent = string.load("\res\5047.nc");    var linestr = string.split(filecontent,'<\r\n>')    for(i=1;#linestr;1){           //增加编码转换,这样就不会显示乱码了        mainForm.listbox.add(string.fromto(linestr[i],0,65001));    } }G_conv = function(str){    var delspace = string.replace(str," ","");    var letter = string.split(delspace);    var num = "";    for(i=1;#letter;1){        //如果字符为空字符则不作处理继续循环        if(letter[i] == " "){            continue ;        }        //强制转换为数字格式,不是数字则返回null,是则返回数字        var k,v = tonumber(letter[i]);        //判断是数字,或者是负号,或者是小数点?        if( (k != null) || (letter[i] == "-")|| (letter[i] == ".")){            //连接这些数字            num = num ++ letter[i];            //如果字符串末尾是数字,则直接输出数字            if(i == #letter){                //console.log(num)                mainForm.Motion_file.add(num);                num ="";            }        }else {    //不是数字,直接输出            if(num != ""){                mainForm.Motion_file.add(num);                num = "";            }            //console.log(num)            mainForm.Motion_file.add(letter[i]);            //console.log(letter[i])        }      }            }var iItem =1;mainForm.button2.oncommand = function(id,event){ var lineCurnum ; mainForm.Motion_file.clear(); G_conv(mainForm.listbox.getItemText(iItem)); iItem++; if(iItem>mainForm.listbox.count){ iItem = 1; } }mainForm.listbox.wndproc = function(hwnd,message,wParam,lParam){    select(message) {        case 0x233/*_WM_DROPFILES*/ {            mainForm.listbox.clear();            var path = win.getDropFile(wParam)[1];            var filecontent = string.load(path);            var linestr = string.split(filecontent,'<\r\n>')            for(i=1;#linestr;1){                   //增加编码转换,这样就不会显示乱码了                mainForm.listbox.add(string.fromto(linestr[i],0,65001));            }                     }        else {        }    }     }mainForm.enableDpiScaling();mainForm.show();return win.loopMessage(); 查看全部

还是分析Gcode代码用的,先前是直接循环获取一行的数据然后解析显示到listbox中,现在需要点击任意一行然后进行解析测试,如果没有选中任意一行那么就继续循环解析:

listbox中有这么个函数:

win.ui.ctrl.listbox() = 列表框\n!listbox.
!listbox.cls = 设计时类名
!listbox.className = 运行时类名
!listbox.clear() = 清除列表框所有内容
!listbox.delete() = 删除当前选中项
!listbox.delete(__) = 删除指定项
!listbox.getItemText(__/*项索引*/) = 获取指定项文本
!listbox.getItemRect(__/*项索引*/) = 获取指定项区块位置\n返回::RECT() 结构体
!listbox.getAt(x,y) = 返回指定客户区坐标所在的项索引.
!listbox.add(__/*请输入文本*/) = 添加列表项到尾部
!listbox.add(__/*请输入文本*/,-1) = 添加列表项到尾部
!listbox.add(__/*请输入文本*/,1) = 添加列表项到头部
!listbox.selIndex = 获取或设置列表框当前选中项\n仅在单选模式下有效,多选模式下请使用 getSelected() setSelected() 函数
!listbox.selText = 获取当前选项的文本\n或根据指定的文本查找并改变选项

对于这些理解的不是很深,所以需要一步步实践下:

姑且会用到

mainForm.listbox.selIndex, mainForm.listbox.selText

于是在界面中增加一个按钮,用来显示哪个被点选了...

console.log(mainForm.listbox.selIndex,mainForm.listbox.selText);

blob.png

实现上面的完整代码如下:

import win.ui;

/*DSG{{*/

mainForm = win.form(text="aardio form";right=561;bottom=654)

mainForm.add(

Motion_file={cls="listbox";left=373;top=10;right=552;bottom=530;edge=1;items={};z=2};

button={cls="button";text="加载";left=16;top=542;right=173;bottom=591;z=3};

button2={cls="button";text="转换";left=197;top=541;right=551;bottom=590;z=4};

button3={cls="button";text="获取谁被点选了";left=20;top=598;right=177;bottom=647;z=5};

listbox={cls="listbox";left=11;top=9;right=361;bottom=529;edge=1;items={};vscroll=1;z=1}

)

/*}}*/


import console;

console.open()

mainForm.button3.oncommand = function(id,event){

//mainForm.msgbox( mainForm.button3.text );

console.log(mainForm.listbox.selIndex,mainForm.listbox.selText);

}



mainForm.button.oncommand = function(id,event){

//mainForm.msgbox( mainForm.button.text );

var filecontent = string.load("\res\5047.nc");

    var linestr = string.split(filecontent,'<\r\n>')

    for(i=1;#linestr;1){   

        //增加编码转换,这样就不会显示乱码了

        mainForm.listbox.add(string.fromto(linestr[i],0,65001));

    }

}



G_conv = function(str){

    var delspace = string.replace(str," ","");

    var letter = string.split(delspace);

    var num = "";

    for(i=1;#letter;1){

        //如果字符为空字符则不作处理继续循环

        if(letter[i] == " "){

            continue ;

        }

        //强制转换为数字格式,不是数字则返回null,是则返回数字

        var k,v = tonumber(letter[i]);

        //判断是数字,或者是负号,或者是小数点?

        if( (k != null) || (letter[i] == "-")|| (letter[i] == ".")){

            //连接这些数字

            num = num ++ letter[i];

            //如果字符串末尾是数字,则直接输出数字

            if(i == #letter){

                //console.log(num)

                mainForm.Motion_file.add(num);

                num ="";

            }

        }else {    //不是数字,直接输出

            if(num != ""){

                mainForm.Motion_file.add(num);

                num = "";

            }

            //console.log(num)

            mainForm.Motion_file.add(letter[i]);

            //console.log(letter[i])

        }

  

    }

  

     

     

}

var iItem =1;

mainForm.button2.oncommand = function(id,event){

var lineCurnum ;

mainForm.Motion_file.clear();

G_conv(mainForm.listbox.getItemText(iItem));

iItem++;

if(iItem>mainForm.listbox.count){

iItem = 1;

}

}



mainForm.listbox.wndproc = function(hwnd,message,wParam,lParam){

    select(message) {

        case 0x233/*_WM_DROPFILES*/ {

            mainForm.listbox.clear();

            var path = win.getDropFile(wParam)[1];

            var filecontent = string.load(path);

            var linestr = string.split(filecontent,'<\r\n>')

            for(i=1;#linestr;1){   

                //增加编码转换,这样就不会显示乱码了

                mainForm.listbox.add(string.fromto(linestr[i],0,65001));

            }

             

        }

        else {

        }

    }

     

}



mainForm.enableDpiScaling();

mainForm.show();


return win.loopMessage();


上位机学习之aardio笔记3

回复

admin 回复了问题 • 1 人关注 • 1 个回复 • 2370 次浏览 • 2017-06-19 19:07 • 来自相关话题

(转)C语言实现卡尔曼滤波算法程序

admin 发表了文章 • 2 个评论 • 13519 次浏览 • 2017-06-10 14:19 • 来自相关话题

非常感谢原作者,我在这个的基础上转换成纯整形运算。STM32F103 12位ADC先放大1000倍再运算,理论上可以保留小数点后三位的结果。效果非常不错,运算速度也快,72M时钟 1-2uS左右(根据MDK周期数)。]uint32_t KalmanFilter(int32_t ResrcData)
{
    /*-------------------------------------------------------------------------------------------------------------*/
    /*
            Q:过程噪声,Q增大,动态响应变快,收敛稳定性变坏
            R:测量噪声,R增大,动态响应变慢,收敛稳定性变好
    */
    /*-------------------------------------------------------------------------------------------------------------*/
    static int32_t R = (int32_t)(128*1024);
    static int32_t Q = (int32_t)4;
    static uint32_t Counter1 = 0;
    static uint32_t Counter2 = 0;
    static int32_t x_last = 0;
        static int32_t p_last;   // 应赋初始估计值
    int32_t x_mid;
    int32_t x_now;
    int32_t p_mid ;
    int32_t p_now;

    ResrcData *= 1024;
    x_now = ResrcData - x_last;
    if(x_now < 0)
    {
        x_now *= -1; // 取绝对值
    }
    if(x_now >= 32*1024)   // 如果测量值连续比估计值大或小 相信测量值,加速迭代
    {
        Counter1++;
        Counter2 = 0;
        if(Counter1 > 10)
        {
            R = 512;;
            Q = 128;
        }
    }
    else                 // 数据比较稳定,加强滤波 
    {
        Counter1 = 0;
        Counter2++;
        if(Counter2 > 10)  
        {
            R = (int32_t)(128*1024);
            Q = (int32_t)4;
        }
    }
    x_mid = x_last;   // x_last=x(k-1|k-1),x_mid=x(k|k-1)
    p_mid = p_last + Q; // p_mid=p(k|k-1),p_last=p(k-1|k-1),Q=噪声
//    kg = p_mid/(p_mid + R); //kg为kalman filter,R为噪声
//    x_now = x_mid+kg*(ResrcData - x_mid);// 估计出的最优值
    x_now = x_mid + (p_mid*(ResrcData - x_mid))/(p_mid + R);
//    p_now = (1 - kg)*p_mid; // 最优值对应的covariance
    p_now = p_mid - p_mid*p_mid/(p_mid + R); // 最优值对应的covariance
    p_last = p_now;  // 更新covariance值
    x_last = x_now;  // 更新系统状态值
    x_now /= 1024;
    if((x_now > 4096)||( x_now < 0))
    {
        x_last = ResrcData;
        p_now = ResrcData;
        x_now = ResrcData/1024;
    }
    return (u32)x_now;
}引用自:https://www.amobbs.com/thread-5675036-1-3.html 卡尔曼滤波算法c语言实现 2: https://www.amobbs.com/forum.p ... ht%3D卡尔曼 查看全部

非常感谢原作者,我在这个的基础上转换成纯整形运算。STM32F103 12位ADC先放大1000倍再运算,理论上可以保留小数点后三位的结果。
效果非常不错,运算速度也快,72M时钟 1-2uS左右(根据MDK周期数)。]

uint32_t KalmanFilter(int32_t ResrcData)
{
    /*-------------------------------------------------------------------------------------------------------------*/
    /*
            Q:过程噪声,Q增大,动态响应变快,收敛稳定性变坏
            R:测量噪声,R增大,动态响应变慢,收敛稳定性变好
    */
    /*-------------------------------------------------------------------------------------------------------------*/
    static int32_t R = (int32_t)(128*1024);
    static int32_t Q = (int32_t)4;
    static uint32_t Counter1 = 0;
    static uint32_t Counter2 = 0;
    static int32_t x_last = 0;
        static int32_t p_last;   // 应赋初始估计值
    int32_t x_mid;
    int32_t x_now;
    int32_t p_mid ;
    int32_t p_now;

    ResrcData *= 1024;
    x_now = ResrcData - x_last;
    if(x_now < 0)
    {
        x_now *= -1; // 取绝对值
    }
    if(x_now >= 32*1024)   // 如果测量值连续比估计值大或小 相信测量值,加速迭代
    {
        Counter1++;
        Counter2 = 0;
        if(Counter1 > 10)
        {
            R = 512;;
            Q = 128;
        }
    }
    else                 // 数据比较稳定,加强滤波 
    {
        Counter1 = 0;
        Counter2++;
        if(Counter2 > 10)  
        {
            R = (int32_t)(128*1024);
            Q = (int32_t)4;
        }
    }
    x_mid = x_last;   // x_last=x(k-1|k-1),x_mid=x(k|k-1)
    p_mid = p_last + Q; // p_mid=p(k|k-1),p_last=p(k-1|k-1),Q=噪声
//    kg = p_mid/(p_mid + R); //kg为kalman filter,R为噪声
//    x_now = x_mid+kg*(ResrcData - x_mid);// 估计出的最优值
    x_now = x_mid + (p_mid*(ResrcData - x_mid))/(p_mid + R);
//    p_now = (1 - kg)*p_mid; // 最优值对应的covariance
    p_now = p_mid - p_mid*p_mid/(p_mid + R); // 最优值对应的covariance
    p_last = p_now;  // 更新covariance值
    x_last = x_now;  // 更新系统状态值
    x_now /= 1024;
    if((x_now > 4096)||( x_now < 0))
    {
        x_last = ResrcData;
        p_now = ResrcData;
        x_now = ResrcData/1024;
    }
    return (u32)x_now;
}



引用自:https://www.amobbs.com/thread-5675036-1-3.html

卡尔曼滤波算法c语言实现 2: https://www.amobbs.com/forum.p ... ht%3D卡尔曼

使用VS2015配合stm32cubemx开发嵌入式STM32-补充

萬~崧~霖 发表了文章 • 1 个评论 • 1944 次浏览 • 2017-05-28 13:10 • 来自相关话题

好吧,我实在不知道怎么给之前的文章追加内容了,老是报:因为最近老有人问这个东西..说建个QQ群,不感兴趣的别喷啊QQ群:310604551 查看全部

好吧,我实在不知道怎么给之前的文章追加内容了,老是报:blob.png


因为最近老有人问这个东西..说建个QQ群,不感兴趣的别喷啊

QQ群:310604551

STM32F042F6P6生成HID工程模拟USB鼠标.

井底添蛙 发表了文章 • 2 个评论 • 4291 次浏览 • 2017-05-24 20:12 • 来自相关话题

就是这个板子,淘宝59可买直接上工程配置了。打开SWD调试,开引脚映射,打开USB(由于引脚占用,USB必须引脚映射后才能开启),设置好对应按键和LED的引脚输出输入模式:设置系统时钟,这里进去后自动设置:设置USB模式,进入GPIO配置:设置好按键和LED的输入输出模式,按键为上拉输入,当按键按下时检测为低:配置工程输出:设置工程名、工程路径、IDE:点击生成工程,等待一会:工程生成完后可直接打开,Keil对于STM32F0/L0系列的单片机是免费授权的,大家可以不用去下盗版破解,直接到官网下载最新的Keil就可以了,新的Keil编译似乎快了不少,详情:http://www2.keil.com/stmicroelectronics-stm32/mdk打开工程,编译,下载(我这里用的是ST-LINK下载),下载完成后,插上USB线到电脑上,会自动识别新设备,如下:可以改以下文件修改设备名称等:修改后编译、下载,电脑里检测的设备名称就已经变了:下面我们来修改main.c,添加按键检测和LED灯代码,当按下按键时,灯就会亮,松开后就灭,在while(1)下添加如下代码: if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin) == 0)
 {
   HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
 }
 else
   HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);然后编译,下载,重新运行之后是不是当按下按键的时候LED就亮了呢?继续添加USB鼠标的代码,在main.c的程序头加入如下头文件:#include "usbd_hid.h"在main函数中定义一个4位数组,用来存放要发送到电脑的鼠标动作信息:  /*
 * buffer[0] - bit0: Left button 左键
 *             bit1: Right button 右键
 *             bit2: Middle button 中键
 * buffer[1] - Cursor movement X axis 水平移动
 * buffer[2] - Cursor movement Y axis 垂直移动
 * buffer[3] - Wheel vertical movement 滚轮转动
 */char buffer[4] = {0x00, 10, 10, 0};在按键检测的判断中添加一条发送语句:USBD_HID_SendReport(&hUsbDeviceFS, buffer, 4);再次编译下载并重新运行,USB插到电脑上后,按下按键,LED亮并且电脑上鼠标会向右下方移动。鼠标的其它参数输出请自行补充。更多可关注smilefrog.net 查看全部

就是这个板子,淘宝59可买

image.png

直接上工程配置了。

打开SWD调试,开引脚映射,打开USB(由于引脚占用,USB必须引脚映射后才能开启),设置好对应按键和LED的引脚输出输入模式:

设置系统时钟,这里进去后自动设置:

设置USB模式,进入GPIO配置:

设置好按键和LED的输入输出模式,按键为上拉输入,当按键按下时检测为低:

配置工程输出:设置工程名、工程路径、IDE:

点击生成工程,等待一会:

工程生成完后可直接打开,Keil对于STM32F0/L0系列的单片机是免费授权的,大家可以不用去下盗版破解,直接到官网下载最新的Keil就可以了,新的Keil编译似乎快了不少,详情:http://www2.keil.com/stmicroelectronics-stm32/mdk

打开工程,编译,下载(我这里用的是ST-LINK下载),下载完成后,插上USB线到电脑上,会自动识别新设备,如下:

可以改以下文件修改设备名称等:

修改后编译、下载,电脑里检测的设备名称就已经变了:

下面我们来修改main.c,添加按键检测和LED灯代码,当按下按键时,灯就会亮,松开后就灭,在while(1)下添加如下代码:

 if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin) == 0)
 {
   HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
 }
 else
   HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);

然后编译,下载,重新运行之后是不是当按下按键的时候LED就亮了呢?

继续添加USB鼠标的代码,在main.c的程序头加入如下头文件:

#include "usbd_hid.h"

在main函数中定义一个4位数组,用来存放要发送到电脑的鼠标动作信息:

  /*
 * buffer[0] - bit0: Left button 左键
 *             bit1: Right button 右键
 *             bit2: Middle button 中键
 * buffer[1] - Cursor movement X axis 水平移动
 * buffer[2] - Cursor movement Y axis 垂直移动
 * buffer[3] - Wheel vertical movement 滚轮转动
 */char buffer[4] = {0x00, 10, 10, 0};

在按键检测的判断中添加一条发送语句:

USBD_HID_SendReport(&hUsbDeviceFS, buffer, 4);

再次编译下载并重新运行,USB插到电脑上后,按下按键,LED亮并且电脑上鼠标会向右下方移动。鼠标的其它参数输出请自行补充。


更多可关注smilefrog.net

基于Cortex-M系列CPU的异步事件驱动中间件

萬~崧~霖 发表了文章 • 3 个评论 • 2596 次浏览 • 2017-01-01 18:51 • 来自相关话题

    对于stm32这类cpu来说,没有MMU意味着不能使用linux,即使勉强上ulinux也非常吃力。目前的现状是各个cpu系列的编程区别甚大,另一个问题就是代码复用率太低了。基本上每做一个项目或工程都需要重新移植驱动代码,或多或少的都得重新做驱动适配等重复性工作,况且,此类情况带来的另一个严重问题是代码接口前后不统一,试想,很多人对于同一个外围器件比如最简单的DS18B20,在不同的CPU上写出了几个版本的驱动程序,由此带来的问题是,产品的业务代码将会变得难以维护,因为驱动层的访问接口不统一,导致业务层代码的复用率就更加的低下了。    再者,对于Linux系统之所以代码利用率非常高(有非常丰富的系统库和三方库)就是因为其系统具有层的概念,各层之间相互协调工作,通过系统提供的层间接口统一访问不同层之间的代码,如:应用层操作硬件的时候面向的是驱动层,并不直接操作具体的硬件寄存器等。即可做到很好的层间代码解耦。应用层程序员甚至不需要具体的硬件型号是什么,只需要遵守系统或框架提供的层间访问接口即可轻松的完成硬件操作。    但是,目前在STM32之类的cpu中并没有一个合适的类似Linux的系统或框架来支撑我们的产品快速迭代和开发,以此来降低产品开发的难度和提高代码利用率降低时间成本。    鉴于以上情况,本人在参考linux一些理论的情况下编写出嵌入式VFS异步事件框架,具有以下特点:    1.多平台适配,可以经过适配不同的RTOS和不同的CPU。目前支持STM32全系列,其他的不爱搞。    2.提供一个异步事件驱动框架,通过注册事件,将会以线程级异步回调注册事件的回调。    3.提供常用的内核定时器驱动,信号驱动,延时信号驱动,SIM800驱动,IIC核心,SPI核心,串口驱动,多线程日志输出等。    4.提供统一的应用层访问接口,框架向上屏蔽硬件细节,向下屏蔽cpu差异。    5.框架内核运行时异常和错误捕捉    6.集成丰富的三方库,TEA加密,BASE64,YMODEM,VSPI,NANOPB,BOOTLOADER,通用数据传输流协议WDATA等。    7.提供统一的片内FLASH访问系统。    8.提供功能强大的SHELL交互式接口    9.提供一个内置的动态代码载入器,简单说就是可以像安卓一样安装APP,运行多个APP,也可随时关闭APP。    。。。。。。还有很多,上图看看代码例子吧!!    RTC访问:此代码是SHELL系统中RTC异步调回,用于从基于串口的SHELL系统操作RTC....SHELL交互式系统:暂时就这些了,不爱写了,玩去...... 查看全部

    对于stm32这类cpu来说,没有MMU意味着不能使用linux,即使勉强上ulinux也非常吃力。目前的现状是各个cpu系列的编程区别甚大,另一个问题就是代码复用率太低了。基本上每做一个项目或工程都需要重新移植驱动代码,或多或少的都得重新做驱动适配等重复性工作,况且,此类情况带来的另一个严重问题是代码接口前后不统一,试想,很多人对于同一个外围器件比如最简单的DS18B20,在不同的CPU上写出了几个版本的驱动程序,由此带来的问题是,产品的业务代码将会变得难以维护,因为驱动层的访问接口不统一,导致业务层代码的复用率就更加的低下了。

    再者,对于Linux系统之所以代码利用率非常高(有非常丰富的系统库和三方库)就是因为其系统具有层的概念,各层之间相互协调工作,通过系统提供的层间接口统一访问不同层之间的代码,如:应用层操作硬件的时候面向的是驱动层,并不直接操作具体的硬件寄存器等。即可做到很好的层间代码解耦。应用层程序员甚至不需要具体的硬件型号是什么,只需要遵守系统或框架提供的层间访问接口即可轻松的完成硬件操作。

    但是,目前在STM32之类的cpu中并没有一个合适的类似Linux的系统或框架来支撑我们的产品快速迭代和开发,以此来降低产品开发的难度和提高代码利用率降低时间成本。

    鉴于以上情况,本人在参考linux一些理论的情况下编写出嵌入式VFS异步事件框架,具有以下特点:

    1.多平台适配,可以经过适配不同的RTOS和不同的CPU。目前支持STM32全系列,其他的不爱搞。

    2.提供一个异步事件驱动框架,通过注册事件,将会以线程级异步回调注册事件的回调。

    3.提供常用的内核定时器驱动,信号驱动,延时信号驱动,SIM800驱动,IIC核心,SPI核心,串口驱动,多线程日志输出等。

    4.提供统一的应用层访问接口,框架向上屏蔽硬件细节,向下屏蔽cpu差异。

    5.框架内核运行时异常和错误捕捉

    6.集成丰富的三方库,TEA加密,BASE64,YMODEM,VSPI,NANOPB,BOOTLOADER,通用数据传输流协议WDATA等。

    7.提供统一的片内FLASH访问系统。

    8.提供功能强大的SHELL交互式接口

    9.提供一个内置的动态代码载入器,简单说就是可以像安卓一样安装APP,运行多个APP,也可随时关闭APP。

    。。。。。。还有很多,上图看看代码例子吧!!


blob.png

    


RTC访问:

此代码是SHELL系统中RTC异步调回,用于从基于串口的SHELL系统操作RTC....

QQ截图20170101185353.png


SHELL交互式系统:

blob.png

暂时就这些了,不爱写了,玩去......

常用的各种滤波算法

xiaohuihui 回复了问题 • 11 人关注 • 3 个回复 • 3934 次浏览 • 2016-12-17 15:20 • 来自相关话题