本帖最后由 lcofjp 于 2014-9-8 18:41 编辑
前端时间晒了自己入手的,大概了解了一下之后,发现8位单片机并不适合我玩,因为我习惯了32位单片机的高大上(8位机基本没用过,起步就是16位的MSP430),所以后来又入手了。
说说我选择PIC32的理由(这个纯属个业余爱好,就是玩,不用于任何产品),因为平时较多的时候使用Mac Book,Microchip的MPLAB X开发环境是跨平台的,可以运行在windows、linux以及OS X上,能在OS X上很方便玩起来的单片机绝对不多(虽然有GCC这种跨平台神器,但是大家都知道,新手根本玩不转这东西);另外MPLAB X开发环境以及XC系列编译器是免费的,虽然免费的XC编译器好像很渣的样子(不能选择优化)。
PIC32主要包括两大系列,PIC32MX和PIC32MZ,本文主要针对PIC32MX795F512L。PIC32MX7xx采用MIPS32® M4K内核,工作电压2.3V-3.6V,最高主频80MHz。
这几天在看一本书《32位单片机C语言编程基于PIC32》,英文名《Programming 32-bit Microcontrollers in C Exploring the PIC32》(下载链接:https://download.eeworld.com.cn/download/lcofjp/62303),在此分享一些心得。
PIC32也拥有像STM32类似的外设库(PIC32MX Peripheral Library),在使用的时候包含plib.h即可。先来说说IO口,PIC32提供两种调试接口,JTAG和ICSP/ICD接口,要使用PORTA的部分引脚作为IO口,必须禁止JTAG接口:DDPCONbits.JTAGEN = 0; PORTB的大部分引脚与ADC输入引脚复用,复位时被配置为模拟功能,若要作为IO口使用,则需配置ADC模块: AD1PCFG = 0xFFFF; 如果某个外围模块的输入输出引脚与IO端口复用,那么一旦启用该外围设备,它就将完全控制该IO端口,与方向控制寄存器(TRISx)的内容无关,然而在8位架构中,即使该模块需要使用这些引脚,用户也得自己制定每个引脚的正确方向。
PIC32的中断分为两种工作模式:单向量工作模式和多向量工作模式。单向量工作模式只有一个中断函数,所有中断都在同一个函数中得到响应(8位单片机基本都是这种模式),可想而知,如果有多个中断要响应,则要判断多个标志位才能确定是产生了哪个中断,因此这种中断响应的延迟很大。多向量工作模式的话,和ARM cortex-M3的原理差不多,可以每个外设模块使用一个中断向量,最多可达64个中断向量。中断优先级分为两种,组优先级和子优先级,组优先级有0-7共8个,上电时,所有中断源的优先级都被默认地设定为ipl0,并屏蔽所有的中断。在相同的组优先级内,还有两个数据位用于定义4个子优先级。如果有2个组优先级相同的事件发生,那么子优先级高者将先被响应。每款PIC32单片机都定义了各种中断源的默认相对优先级。当其他条件都无效时(组优先级和子优先级都相同),将根据自然顺序决定响应同时发生的多个事件中的哪一个。
中断函数的写法(其中一种,比较简单的写法):
void __ISR(VECTOR, IPL) HandlerName(void);
其中VECTOR指定要响应的某个中断向量,IPL指定中断的优先级。
例如:
void __ISR(_TIMER_1_VECTOR, IPL0SOFT) Timer1ISR(void)
{
}
最后来个流水灯的示例吧,调了半个晚上才弄出来,问题在于要给FPB进行分频时,就不要执行SYSTEMConfigPerformance函数了,它会把FPB调到系统能接受的最大值,导致频率不对。
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <plib.h>
- // DEVCFG3
- // USERID = No Setting
- #pragma config FSRSSEL = PRIORITY_7 // SRS Select (SRS Priority 7)
- #pragma config FMIIEN = ON // Ethernet RMII/MII Enable (MII Enabled)
- #pragma config FETHIO = ON // Ethernet I/O Pin Select (Default Ethernet I/O)
- #pragma config FCANIO = ON // CAN I/O Pin Select (Default CAN I/O)
- #pragma config FUSBIDIO = ON // USB USID Selection (Controlled by the USB Module)
- #pragma config FVBUSONIO = ON // USB VBUS ON Selection (Controlled by USB Module)
- // DEVCFG2
- #pragma config FPLLIDIV = DIV_2 // PLL Input Divider (4x Divider)
- #pragma config FPLLMUL = MUL_18 // PLL Multiplier (18x Multiplier)
- #pragma config UPLLIDIV = DIV_1 // USB PLL Input Divider (1x Divider)
- #pragma config UPLLEN = OFF // USB PLL Enable (Disabled and Bypassed)
- #pragma config FPLLODIV = DIV_1 // System PLL Output Clock Divider (PLL Divide by 1)
- // DEVCFG1
- #pragma config FNOSC = PRIPLL // Oscillator Selection Bits (Primary Osc (XT,HS,EC))
- #pragma config FSOSCEN = ON // Secondary Oscillator Enable (Enabled)
- #pragma config IESO = ON // Internal/External Switch Over (Enabled)
- #pragma config POSCMOD = XT // Primary Oscillator Configuration (XT osc mode)
- #pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin (Disabled)
- #pragma config FPBDIV = DIV_8 // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/8)
- #pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)
- #pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576)
- #pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
- // DEVCFG0
- #pragma config DEBUG = OFF // Background Debugger Enable (Debugger is disabled)
- #pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select (ICE EMUC2/EMUD2 pins shared with PGC2/PGD2)
- #pragma config PWP = OFF // Program Flash Write Protect (Disable)
- #pragma config BWP = OFF // Boot Flash Write Protect bit (Protection Disabled)
- #pragma config CP = OFF // Code Protect (Protection Disabled)
- /*
- * KEY1,2,3 === RD6, RD7, RD13
- * LED1,2,3 === RD0, RD1, RD2
- */
- volatile uint32_t value = 0;
- int main(int argc, char** argv) {
- uint32_t old_value = 0;
- //SYSTEMConfigPerformance(72000000L);
- DDPCONbits.JTAGEN = 0;
- TRISDCLR = 7;
- PR1 = 35155;
- T1CON = 0x8030;
- INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);// INTEnableSystemMultiVectoredInt();
- mT1SetIntPriority(1);
- mT1IntEnable(1);
- INTEnableInterrupts();
- while(1)
- {
- if (old_value != value)
- {
- LATD = value;
- old_value = value;
- }
- }
- return (EXIT_SUCCESS);
- }
- void __ISR(_TIMER_1_VECTOR, IPL1SOFT) Timer1ISR(void)
- {
- switch(value)
- {
- case 1:
- value = 2;
- break;
- case 2:
- value = 4;
- break;
- case 4:
- value = 1;
- break;
- default:
- value = 1;
- break;
- }
- mT1ClearIntFlag();
- }
复制代码