欢迎访问 生活随笔!

尊龙游戏旗舰厅官网

当前位置: 尊龙游戏旗舰厅官网 > 编程语言 > >内容正文

asp.net

【.net micro framework portingkit -尊龙游戏旗舰厅官网

发布时间:2025/1/21 18 豆豆
尊龙游戏旗舰厅官网 收集整理的这篇文章主要介绍了 【.net micro framework portingkit - 08】gpio驱动 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

要点亮led灯或获得输入io的状态应该是比较容易的,打开端口时钟,然后读写相关的gpio寄存器就可以了,但是要实现一个输入中断,就要费些周折了。

对stm32(cortex-m3)的芯片,要实现一个gpio中断一般需要如下几步:

1、  配置时钟控制器寄存器(rcc)的apb2rstr,确保对应的gpioa ~ gpiog时钟使能。

2、  对gpio寄存器的crl(或crh)要设置正确的输入模式,如浮空输入模式(对接收io中断来说,当然要设置成输入模式)。

3、  要通过afio寄存器配置中断的输入来源,对stm32芯片来说,具有19路exti中断线,其中3路分别连接pvd输出、rtc闹钟事件及usb唤醒事件,剩下的对gpioa ~ gpiog 7*16=112个io点来说,同时只能配置16路io输入中断。

4、  接下来要配置exit寄存器,根据需要来配置是上升沿触发中断、还是下降沿触发中断或两者都触发。

5、  而后比较重要的是, 要配置nvic的setena寄存器,让对应的exti0、exti1、exti2、exti3、exti4、exti9_5或exti15_10中断位使能,此外还要配置各中断的优先级(前提是中断优先级分组寄存器已配置完毕)。

6、  最后我们要设置中断向量表(该向量表要重定位到内存中,以便于动态修改),在exti0、exti1、exti2、exti3、exti4、exti9_5或exti15_10对应的位置,放入我们的中断函数的入口地址。

 

和pc平台程序开发不同,基本上你每做一步,都可以很直观的看到你的进展和成果,但对嵌入式开发来说,如果上述几步有任何一个环节出了问题,你的进展都是零,有时候你会花上一天的时间去反复核实每个寄存器的值是否正确,以期获得你希望的结果。所以说嵌入式开发是惊喜的型的,要么成,要么不成,一线之隔!

接下来我们说一下gpio实现的详细步骤,首先在cortexm3.h头文件中添加gpio相关的寄存器描述:

  • struct cortexm3_gpio  
  •  
  • {  
  •  
  •   static const uint32 c_base = 0x40010800;  
  •  
  •   static const uint32 a = 0;  
  •  
  •   static const uint32 b = 1;  
  •  
  •   static const uint32 c = 2;  
  •  
  •   static const uint32 d = 3;  
  •  
  •   static const uint32 e = 4;  
  •  
  •   static const uint32 f = 5;   
  •  
  •   static const uint32 g = 6;   
  •  
  •   static const uint32 gpio_mode_null = 0x00;  
  •  
  •   static const uint32 gpio_mode_speed_10mhz = 0x01;  
  •  
  •   static const uint32 gpio_mode_speed_2mhz = 0x02;  
  •  
  •   static const uint32 gpio_mode_speed_50mhz = 0x03;  
  •  
  •   static const uint32 gpio_mode_in_floating = 0x04;  
  •  
  •     /****/ volatile uint32   crl;  //配置寄存器  
  •  
  •   /****/ volatile uint32   crh;  
  •  
  •   /****/ volatile uint32   idr;  //数据寄存器  
  •  
  •   /****/ volatile uint32   odr;  
  •  
  •   /****/ volatile uint32   bsrr; //置位复位寄存器  
  •  
  •   /****/ volatile uint32   brr;  //复位寄存器  
  •  
  •   /****/ volatile uint32   lckr; //锁定寄存器  
  •  
  • };  
  •  
  • struct cortexm3_exti  
  •  
  • {  
  •  
  •   static const uint32 c_base = 0x40010400;  
  •  
  •   /****/ volatile uint32  imr;  
  •  
  •   /****/ volatile uint32  emr;  
  •  
  •   /****/ volatile uint32  rtsr;  
  •  
  •   /****/ volatile uint32  ftsr;  
  •  
  •   /****/ volatile uint32  swier;  
  •  
  •   /****/ volatile uint32  pr;  
  •  
  • };  
  •  
  • struct cortexm3_afio  
  •  
  • {  
  •  
  •   static const uint32 c_base = 0x40010000;    
  •  
  •   /****/ volatile uint32 evcr;  
  •  
  •   /****/ volatile uint32 mapr;  
  •  
  •   /****/ volatile uint32 exticr[4];  
  •  
  • };  
  •  
  • 由于nvic相关的代码我们已经在《nvic中断处理》说过了,这里就不重复了。

    对.net micro framework的架构来说,要实现如下几个接口:

    1、cpu_gpio_initialize

    2、cpu_gpio_uninitialize

    3、cpu_gpio_attributes

    4、cpu_gpio_disablepin

    5、cpu_gpio_enableoutputpin

    6、cpu_gpio_enableinputpin

    7、cpu_gpio_enableinputpin2

    8、cpu_gpio_getpinstate

    9、cpu_gpio_setpinstate

    10、cpu_gpio_getpincount

    11、cpu_gpio_getpinsmap

    12、cpu_gpio_getsupportedresistormodes

    13、cpu_gpio_getsupportedinterruptmodes

    14、cpu_gpio_pinisbusy

    15、cpu_gpio_reservepin

    16、cpu_gpio_getdebounce

    17、cpu_gpio_setdebounce

    考虑到难易程度和篇幅,我们只介绍cpu_gpio_initialize、cpu_gpio_enableoutputpin、 cpu_gpio_enableinputpin和exti_irqhandler 中断函数的具体实现。

  • bool gpio_driver::initialize()  
  •  
  • {  
  •  
  •          cortexm3_afio &afio = cortexm3::afio();  
  •  
  •     for(int i=0;i<4;i )   
  •  
  •     {  
  •  
  •        afio.exticr[i]=0x0000;  
  •  
  •     }          
  •  
  • cortexm3_exti &exti= cortexm3::exti();      
  •  
  •     exti.imr = 0x00000000;  
  •  
  •     exti.emr = 0x00000000;  
  •  
  •     exti.rtsr = 0x00000000;   
  •  
  •     exti.ftsr = 0x00000000;   
  •  
  •     exti.pr = 0x0007ffff;  
  •  
  •     //nvic   
  •  
  •     if(!cpu_intc_activateinterruptex(cortexm3_nvic::c_irq_index_exti0,(uint32)(void *)exti_irqhandler ))   return false;  
  •  
  •          //略  
  •  
  •     return true;  
  •  
  • }  
  •  
  • 其中比较重要的是cpu_intc_activateinterruptex函数,它可动态设置c_irq_index_exti0中断所对应的中断函数的入口地址。

  • void gpio_driver::enableoutputpin(gpio_pin pin, bool initialstate)  
  •  
  • {  
  •  
  •     assert(pin < c_maxpins);          
  •  
  •     uint32 port = pintoport(pin);   
  •  
  •          uint32 bit = pintobit(pin);  
  •  
  •     uint32 pos = (bit % 8)<<2;  
  •  
  •          cortexm3_gpio &gpio= cortexm3::gpio(port);      
  •  
  •     //通用推挽输出模式  
  •  
  •     if(bit<8)  
  •  
  •     {          
  •  
  •        gpio.crl = (gpio.crl & ~(0x0f << pos)) | (cortexm3_gpio::gpio_mode_speed_50mhz << pos);  
  •  
  •     }  
  •  
  •          else 
  •  
  •          {  
  •  
  •             gpio.crh = (gpio.crh & ~(0x0f << pos)) | (cortexm3_gpio::gpio_mode_speed_50mhz << pos);  
  •  
  •          }  
  •  
  •    
  •  
  •     //初值  
  •  
  •     if(initialstate) gpio.bsrr = 0x1 << bit;  
  •  
  •     else gpio.brr = 0x1 << bit;  
  •  
  • }  
  •  
  • 输出默认为通用推挽输出模式,你也可以根据实际需要进行必要的调整。

  • bool gpio_driver::enableinputpin(gpio_pin pin, bool glitchfilterenable, gpio_interrupt_service_routine isr, void *pinisrparam, gpio_int_edge intedge, gpio_resistor resistorstate)  
  •  
  • {  
  •  
  •     assert(pin < c_maxpins);          
  •  
  •     uint32 port = pintoport(pin);   
  •  
  •          uint32 bit = pintobit(pin);  
  •  
  •     uint32 pos = (bit % 8)<<2;  
  •  
  •          cortexm3_gpio &gpiocortexm3::gpio(port);      
  •  
  •     //浮空输入  
  •  
  •     if(bit<8)  
  •  
  •     {          
  •  
  •        gpio.crl = (gpio.crl & ~(0x0f << pos))| (cortexm3_gpio::gpio_mode_in_floating << pos);  
  •  
  •     }  
  •  
  •          else  
  •  
  •          {  
  •  
  •             gpio.crh = (gpio.crh & ~(0x0f << pos))| (cortexm3_gpio::gpio_mode_in_floating << pos);  
  •  
  •          }  
  •  
  •     //中断输入源配置(afio)  
  •  
  •     cortexm3_afio &afio = cortexm3::afio();  
  •  
  •     afio.exticr[bit >> 2] &= ~(0x0f << (0x04 * (bit & 0x03)));  
  •  
  •     afio.exticr[bit >> 2] |= port << (0x04 * (bit & 0x03));  
  •  
  •          cortexm3_exti &exti=cortexm3::exti();  
  •  
  •     if(isr)  
  •  
  •     {  
  •  
  •         switch(intedge)  
  •  
  •         {  
  •  
  •             case gpio_int_none:   //无中断  
  •  
  •                 exti.imr &= ~(0x1<<bit);                                      
  •  
  •                 return false;  
  •  
  •             case gpio_int_edge_low:   //下降沿中断  
  •  
  •             case gpio_int_level_low:  
  •  
  •                 exti.imr |= 0x1<<bit;       
  •  
  •                                      exti.ftsr |= 0x1<<bit;        //下降沿有效  
  •  
  •                                      exti.rtsr &= ~(0x1<<bit);  //上升沿无效  
  •  
  •                 break;  
  •  
  •             //略  
  •  
  •             default:  
  •  
  •                 assert(0);  
  •  
  •                 return false;  
  •  
  •         }  
  •  
  •     }                   
  •  
  •                      
  •  
  •     return true;  
  •  
  • }  
  •  
  • gpio输入的实现比较繁琐一些,可以根据需要仅把端口配置成输入模式,而不配置相应的中断参数。这样可以通过不断扫描的方式获得输入信号。

  • void gpio_driver::isr(void *param)  
  •  
  • {  
  •  
  •          cortexm3_exti &exti=cortexm3::exti();  
  •  
  •     uint32 interruptsactive = exti.pr;  
  •  
  •     uint32 bitmask  = 0x1, bitindex = 0;  
  •  
  •          while(interruptsactive)  
  •  
  •     {  
  •  
  •         while((interruptsactive & bitmask) == 0)  
  •  
  •         {  
  •  
  •             bitmask  <<= 1;  
  •  
  •              bitindex;  
  •  
  •         }  
  •  
  •         cortexm3_afio &afio = cortexm3::afio();  
  •  
  •         uint32 port = (afio.exticr[bitindex >> 2]>>(0x04 * (bitindex & 0x03))) & 0xf;  
  •  
  •         gpio_pin pin = bittopin( bitindex, port);  
  •  
  •         pin_isr_descriptor& pinisr = g_gpio_driver.m_pinisr[ pin ];  
  •  
  •         pinisr.fire( (void*)&pinisr );  
  •  
  •         interruptsactive ^= bitmask;  
  •  
  •                    exti.pr |= bitmask;  
  •  
  •     }   
  •  
  • }  
  •  
  • 在中断函数中,根据相关寄存器的值来判断哪一个(或同时哪一些)gpio发生的中断,并由此执行业已配置好的异步中断处理函数。

    好了,写完了gpio驱动程序,我们就可以漂漂亮亮的在nativesample中写我们的测试程序了:

  • void isr( gpio_pin pin, bool pinstate, void* param )  
  •  
  • {  
  •  
  •     if(pinstate)    // released, up  
  •  
  •     {  
  •  
  •       cpu_gpio_setpinstate(gpio_driver::pf7,0x0);  
  •  
  •     }  
  •  
  •     else            // pressed, down  
  •  
  •     {  
  •  
  •        cpu_gpio_setpinstate(gpio_driver::pf7,0x1);  
  •  
  •     }  
  •  
  • }  
  •  
  •    
  •  
  • void applicationentrypoint()  
  •  
  • {     
  •  
  •     //led d1 d2 d3 d4     
  •  
  •     cpu_gpio_enableoutputpin(gpio_driver::pf7,false);  
  •  
  •          cpu_gpio_enableoutputpin(gpio_driver::pf8,false);  
  •  
  •    
  •  
  •          //user按钮 = 0x1  
  •  
  •          cpu_gpio_enableinputpin(gpio_driver::pg8,false,isr,gpio_int_edge_both,resistor_pulldown);                      
  •  
  •     while(true)       
  •  
  •     {     
  •  
  •            cpu_gpio_setpinstate(gpio_driver::pf8,!cpu_gpio_getpinstate(gpio_driver::pf8));  
  •  
  •            events_waitforevents( 0, 1000 );         
  •  
  •          }  
  •  
  • }  
  •  
  • 上面的程序比我们最初在《调试初步:点亮led灯》中提到的代码清爽多了,把程序下载到开发板上运行,你会发现d3 led灯以一秒为周期不断地闪烁,而d2 led灯则在user按钮按下时才亮,放开时则灭。

    只要细心 耐心,其实嵌入式开发还是比较容易的,并且功能实现那一刻喜悦的“强度”,是作为pc平台软件开发者所难以企及的

     

    转载于:https://blog.51cto.com/yfsoft/321228

    总结

    以上是尊龙游戏旗舰厅官网为你收集整理的【.net micro framework portingkit - 08】gpio驱动的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得尊龙游戏旗舰厅官网网站内容还不错,欢迎将尊龙游戏旗舰厅官网推荐给好友。

    • 上一篇:
    • 下一篇:
    网站地图