外部中断实验

代码构造均取自野火教程,只是加上了一些注释。

按键和 EXTI 宏定义:

//引脚定义
#define KEY1_INT_GPIO_PORT GPIOA
//GPIOA
#define KEY1_INT_GPIO_CLK RCC_AHB1Periph_GPIOA
//打开AHB1时钟
#define KEY1_INT_GPIO_PIN GPIO_Pin_0
//pin0
#define KEY1_INT_EXTI_PORTSOURCE EXTI_PortSourceGPIOA
//GPIOA中断
#define KEY1_INT_EXTI_PINSOURCE EXTI_PinSource0
//第0引脚中断
#define KEY1_INT_EXTI_LINE EXTI_Line0
//选择EXTI中断源(PA0)
#define KEY1_INT_EXTI_IRQ EXTI0_IRQn
//IRQ通道

#define KEY1_IRQHandler EXTI0_IRQHandler
//中断服务函数

//以下同上
#define KEY2_INT_GPIO_PORT GPIOC
#define KEY2_INT_GPIO_CLK RCC_AHB1Periph_GPIOC
#define KEY2_INT_GPIO_PIN GPIO_Pin_13
#define KEY2_INT_EXTI_PORTSOURCE EXTI_PortSourceGPIOC
#define KEY2_INT_EXTI_PINSOURCE EXTI_PinSource13
#define KEY2_INT_EXTI_LINE EXTI_Line13
#define KEY2_INT_EXTI_IRQ EXTI15_10_IRQn

#define KEY2_IRQHandler EXTI15_10_IRQHandler

嵌套向量中断控制器 NVIC 配置:

 /**
  * @brief  配置嵌套向量中断控制器NVIC
  * @param  无
  * @retval 无
  */
static void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 配置NVIC为优先级组1 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  
  /* 配置中断源:按键1 */
  NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
  /* 配置抢占优先级:1 */
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 配置子优先级:1 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中断通道 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
  /* 配置中断源:按键2,其他使用上面相关配置 */  
  NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
  NVIC_Init(&NVIC_InitStructure);
}


EXTI 中断配置:

 /**
  * @brief  配置 PA0 为线中断口,并设置中断优先级
  * @param  无
  * @retval 无
  */
void EXTI_Key_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; 
EXTI_InitTypeDef EXTI_InitStructure;
  
/*开启按键GPIO口的时钟*/
RCC_AHB1PeriphClockCmd(KEY1_INT_GPIO_CLK|KEY2_INT_GPIO_CLK ,ENABLE);
  
  /* 使能 SYSCFG 时钟 ,使用GPIO外部中断时必须使能SYSCFG时钟*/
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  
  /* 配置 NVIC */
  NVIC_Configuration();
  
/* 选择按键1的引脚 */ 
  GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
  /* 设置引脚为输入模式 */ 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;    
  /* 设置引脚不上拉也不下拉 */
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  /* 使用上面的结构体初始化按键 */
  GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure); 
/* 连接 EXTI 中断源 到key1引脚 */
  SYSCFG_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE,KEY1_INT_EXTI_PINSOURCE);
  /* 选择 EXTI 中断源 */
  EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
  /* 中断模式 */
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  /* 下降沿触发 */
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  
  /* 使能中断/事件线 */
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
  
  /* 选择按键2的引脚 */ 
  GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;  
  /* 其他配置与上面相同 */
  GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);      
/* 连接 EXTI 中断源 到key2 引脚 */
  SYSCFG_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE,KEY2_INT_EXTI_PINSOURCE);
  /* 选择 EXTI 中断源 */
  EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  /* 上升沿触发 */
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
}

EXTI 中断服务函数(一般会把中断函数放入stm32f4xx_it.c文件当中):

void KEY1_IRQHandler(void)
{
  //确保是否产生了EXTI Line中断
	if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) 
	{
		// LED1 取反		
		LED1_TOGGLE;
    //清除中断标志位
		EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);     
	}  
}

void KEY2_IRQHandler(void)
{
  //确保是否产生了EXTI Line中断
	if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) 
	{
		// LED2 取反		
		LED2_TOGGLE;
    //清除中断标志位
		EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);     
	}  
}

理解值和引用-第八章-C#从入门到放弃

Circle c;
c = new Circle(42);
Circle refc;
refc = c;  //c与refc指向同一地址

正确的复制类的方法(包括复制私有数据):

class Circle
{
    private int radius;
    ...
    public Circle Clone()
    {
        //创建新的Circle对象
        Circle clone = new Circle();
        //将私有的数据从this复制到clone
        clone.radius = this.radius;
        
        //返回包含克隆数据的新Circle对象
        return clone;
    }
}

null值:

Circle c = new Circle(42);
Circle copy = null;
...
if(copy == null)
{
    copy = c;
    ...
}

对于值类型,需要将变量生命为可空值类型:

int i = null; //非法
int? i = null; //合法

可空类型的属性:

int? i = null;
...
if(!i.HasValus)
{
    i = 99;
}
else
{
    Console.WriteLine(i.Value);
}

ref:

static void example(ref int a)
{
    a++;
}
static void Main()
{
    int arg = 42;
    example(ref arg);
    //arg=43
}

out:

static void example(out int a)
{
    a = 42;
}
static void Main()
{
    int arg;
    example(out arg);
    //arg=42
}

object:

Circle c;
c = new Circle(42);
object o;
o = c;

创建和管理类和对象 – 第七章 – C# 从入门到放弃

创建构造器的一个例子:

class Circle
{
    private int radius;
    
    public Circle()  //默认构造器
    {
        radius = 0;
    }
    public Circle(int initalRadius)  //重载的构造器
    {
        radius = initialRadius;
    }
    public double Area()
    {
        return Math.PI * radius * radius;
    }
}

使用多文件时的写法:

Circ1.cs内容:

partial class Circle
{
    public Circle()  //默认构造器
    {
        radius = 0;
    }
    public Circle(int initalRadius)  //重载的构造器
    {
        radius = initialRadius;
    }
}

Circ2.cs内容:

partial class Circle
{
    private int radius;
    public double Area()
    {
        return Math.PI * radius * radius;
    }
}

调用自己的字段时,使用this关键字:

class Point
{
    private int x, y;
    private static int objectCount = 0;
    public Point()
    {
        this.x = -1;
        this.y = -1;
        objectCount++;
    }
    public Point(int x, int y)
    {
        this.x = x;
        this.y = y;
        objectCount++;
    }
    public double DistanceTo(Point other)
    {
        int xDiff = this.x - other.x;   //注意此处
        int yDiff = this.y - other.y;
        double distance = Math.Sqrt((xDiff * xDiff) + (yDiff * yDiff));
        return distance;
    }
    public static int ObjectCount() => objectCount;
    //ObjectCount方法返回objectCount的值
}

=======

静态方法/数据使用static标记

只能访问标记为static的其他方法和字段

静态类(不允许被new:

class Math
{
    ...
    public const double PI = 3.14159265358979;
}

匿名类:

var myxxxx = new {Name = "xx", Age = 123};
Console.WriteLine($"Name:{myxxxx.Name},Age:{myxxxx.Age}");


var myyyyy = new {Name = "yy", Age = 321};

myxxxx = myyyyy; //合法,因为具有相同类型

异常处理 – 第六章 – C# 从入门到放弃

基本语法:

try
{
    ...
}
catch(Exception ex) when (ex.GetTypr() != typeof(System.OutOfMenoryException))
{
    ....
}

=====

数据溢出异常的处理:

checked:

int number = int.MaxValue;
checked
{
    int willThrow = number++;
    Console.WriteLine("won't run to here");
}

unchecked:

int number = int.MaxValue;
unchecked
{
    int willThrow = number++;
    Console.WriteLine("will run to here");
}

also:

try
{
    int lhs = 9876543;
    int rhs = 9876543;
    int outcome = 0;
    outcome = checked(lhs * rhs);
}
catch(OverflowException oEx)
{
    result.Text = oex.Message;
}

=====

手动抛出异常:

try
{
    throw new ArgumentOutOfRangeException("error!");
}
catch(ArgumentOutOfRangeException msg)
{
    xxx.Text = msg.Message;
}

finally的用法:

try
{
    DataConnection.Open();
    DataCommand.ExecuteReader();
    ...
    return;
}
finally
{
    DataConnection.Close();
}
//无论是否抛出异常,也无论从什么地方 return 返回,finally 语句块总是会执行,这样你有机会调用 Close 来关闭数据库连接(即使未打开或打开失败,关闭操作永远是可以执行的),以便于释放已经产生的连接,释放资源。 顺便说明,return 是可以放在 try 语句块中的。但不管在什么时机返回,在返回前,finally 将会执行。
//小结
try
{
    // 执行的代码,其中可能有异常。一旦发现异常,则立即跳到 catch 执行。否则不会执行 catch 里面的内容
}
catch
{
    // 除非 try 里面执行代码发生了异常,否则这里的代码不会执行
}
finally
{
    // 不管什么情况都会执行,包括 try catch 里面用了 return , 可以理解为只要执行了 try 或者 catch,就一定会执行 finally
}

K60笔记-模拟舵机控制

本程序使用山外库:http://git.oschina.net/chenxuuu/vcan-K60-V5.3

模拟舵机通过电压大小控制方向(好像是这样w)

所以和电机差不多

先初始化PWM口

ftm_pwm_init(S3010_FTM, S3010_CH,S3010_HZ,100);

然后和控制电机一样

ftm_pwm_duty(S3010_FTM, S3010_CH,1000);

和之前一样,可以把这个封装成函数

#define control_actuator_center 1380
#define control_actuator_min 1260
#define control_actuator_max 1500     //自测
/*!
 *  @brief      舵机输出函数
 *  @since      v1.1
 *  @note       输入值范围-1~1   浮点型
 *  Sample usage:            control_actuator(-0.2);    //输出舵机反向0.2
 */
void control_actuator(float Voltage)
{
    if(Voltage>1)
        Voltage=1;
    else if(Voltage<-1)
        Voltage=-1;

    if(Voltage<0)
    {
        ftm_pwm_duty(S3010_FTM, S3010_CH,(int)((control_actuator_center-control_actuator_min)*Voltage+control_actuator_center));
    }else
    {
        ftm_pwm_duty(S3010_FTM, S3010_CH,(int)((control_actuator_max-control_actuator_center)*Voltage+control_actuator_center));
    }
}

调用栗子

if(key_check(KEY_U) == KEY_DOWN)
{
    dj+=0.01;
    control_actuator(dj);
}
if(key_check(KEY_D) == KEY_DOWN)
{
    dj-=0.01;
    control_actuator(dj);
}

本文所用工程文件:http://git.oschina.net/chenxuuu/K60-test/tree/master/舵机

K60笔记-PWM控制电机

本程序使用山外库:http://git.oschina.net/chenxuuu/vcan-K60-V5.3

首先初始化

    ftm_pwm_init(FTM0, FTM_CH2,10*1000,0);
    //初始化 FTM PWM ,使用 FTM0_CH3,频率为10k ,占空比为 100 / FTM0_PRECISON
    ftm_pwm_init(FTM0, FTM_CH3,10*1000,0);
    ftm_pwm_init(FTM0, FTM_CH4,10*1000,0);
    ftm_pwm_init(FTM0, FTM_CH5,10*1000,0);

PWM驱动

    ftm_pwm_duty(FTM0, FTM_CH6, 10);
    //设置 FTM0_CH6 占空比为 10/FTM0_PRECISON

示例:

/*!
 *     COPYRIGHT NOTICE
 *     Copyright (c) 2013,山外科技
 *     All rights reserved.
 *     技术讨论:山外论坛 http://www.vcan123.com
 *
 *     除注明出处外,以下所有内容版权均属山外科技所有,未经允许,不得用于商业用途,
 *     修改内容时必须保留山外科技的版权声明。
 *
 * @file       main.c
 * @brief      山外K60 平台主程序
 * @author     山外科技
 * @version    v5.2
 * @date       2014-11-03
 */

#include "common.h"
#include "include.h"

/*!
 *  @brief      main函数
 *  @since      v5.2
 *  @note       FTM PWM 电机驱动测试
 */
void main(void)
{
    uint8 i = 0;
    printf("\n*****FTM PWM 电机测试*****\n");

    ftm_pwm_init(FTM0, FTM_CH3,10*1000,80);         //初始化 FTM PWM ,使用 FTM0_CH3,频率为10k ,占空比为 100 / FTM0_PRECISON
                                                    // FTM0_PRECISON 配置 为 100 ,即占空比 为 100%
                                                    // port_cfg.h 里 配置 FTM0_CH3 对应为 PTA6
    gpio_init(PTD15,GPO,0);                         // 使能端 输入为 0

    //山外的电机驱动模块,经过 MOS 管 反相隔离。
    //K60 输出 PWM 为 100% ,实际接入 电机驱动就是 0%
    //K60 输出 使能端 为 低电平,实际接入 电机驱动 使能端就是 高电平

    while(1)
    {
        for(i= 0;i<=100;i+=10)
        {
            ftm_pwm_duty(FTM0,FTM_CH3,i);       //改变 占空比 ,K60 输出 PWM 占空比 逐渐增大,电机逐渐 降速
            DELAY_MS(500);
        }
    }
}

然而感觉这样子好麻烦诶qwq

所以翻出了原来的一个函数

/************电机输出函数*************/
void SetMotorVoltage(float fLeftVoltage,float fRightVoltage)
{
    int nOut;
    if(fLeftVoltage>0)
    {
	ftm_pwm_duty(FTM0,FTM_CH2,0);//左轮正向运动PWM占空比为0
	nOut=(int)(fLeftVoltage*PERIOD);//
	if(nOut>1000)
	{
		nOut=1000;
	}
	ftm_pwm_duty(FTM0,FTM_CH3,nOut);//左轮反向运动PWM占空比为nOut
    }                                                   //左电机正转
    else
    {
	ftm_pwm_duty(FTM0,FTM_CH3,0);//左轮反向运动PWM占空比为0
	fLeftVoltage=-fLeftVoltage;
	nOut=(int)(fLeftVoltage*PERIOD);
	if(nOut>1000)
	{
		nOut=1000;
	}
	ftm_pwm_duty(FTM0,FTM_CH2,nOut);//左轮正向运动PWM占空比为nOut
    }                                                    //左电机反转

    if(fRightVoltage>0)
    {
	ftm_pwm_duty(FTM0,FTM_CH4,0);//右轮正向运动PWM占空比为0
	nOut=(int)(fRightVoltage*PERIOD);
	if(nOut>1000)
	{
		nOut=1000;
	}
	ftm_pwm_duty(FTM0,FTM_CH5,nOut);//右轮反向运动PWM占空比为nOut
    }                                                     //右电机正转
    else
    {
	ftm_pwm_duty(FTM0,FTM_CH5,0);//右轮反向运动PWM占空比为0
	fRightVoltage=-fRightVoltage;
	nOut=(int)(fRightVoltage*PERIOD);
	if(nOut>1000)
	{
		nOut=1000;
	}
	ftm_pwm_duty(FTM0,FTM_CH4,nOut);//右轮正向运动PWM占空比为nOut
    }                                                     //右电机反转
}

这个函数可以直接让电机转

调用时可以这样:

SetMotorVoltage(x,y);
//正值正转,负值反转,xy均为float类型

示例

/*!
 *     COPYRIGHT NOTICE
 *     Copyright (c) 2013,山外科技
 *     All rights reserved.
 *     技术讨论:山外论坛 http://www.vcan123.com
 *
 *     除注明出处外,以下所有内容版权均属山外科技所有,未经允许,不得用于商业用途,
 *     修改内容时必须保留山外科技的版权声明。
 *
 * @file       main.c
 * @brief      山外K60 平台主程序
 * @author     山外科技
 * @version    v5.2
 * @date       2014-11-03
 */

#include "common.h"
#include "include.h"
#include "MK60_adc.h"
#include  "OLED.h"
#define	PERIOD				100				//电压转换PWM比例    待定

/************电机输出函数*************/
void SetMotorVoltage(float fLeftVoltage,float fRightVoltage)
{
    int nOut;
    if(fLeftVoltage>0)
    {
	ftm_pwm_duty(FTM0,FTM_CH2,0);//左轮正向运动PWM占空比为0
	nOut=(int)(fLeftVoltage*PERIOD);//
	if(nOut>1000)
	{
		nOut=1000;
	}
	ftm_pwm_duty(FTM0,FTM_CH3,nOut);//左轮反向运动PWM占空比为nOut
    }                                                   //左电机正转
    else
    {
	ftm_pwm_duty(FTM0,FTM_CH3,0);//左轮反向运动PWM占空比为0
	fLeftVoltage=-fLeftVoltage;
	nOut=(int)(fLeftVoltage*PERIOD);
	if(nOut>1000)
	{
		nOut=1000;
	}
	ftm_pwm_duty(FTM0,FTM_CH2,nOut);//左轮正向运动PWM占空比为nOut
    }                                                    //左电机反转

    if(fRightVoltage>0)
    {
	ftm_pwm_duty(FTM0,FTM_CH4,0);//右轮正向运动PWM占空比为0
	nOut=(int)(fRightVoltage*PERIOD);
	if(nOut>1000)
	{
		nOut=1000;
	}
	ftm_pwm_duty(FTM0,FTM_CH5,nOut);//右轮反向运动PWM占空比为nOut
    }                                                     //右电机正转
    else
    {
	ftm_pwm_duty(FTM0,FTM_CH5,0);//右轮反向运动PWM占空比为0
	fRightVoltage=-fRightVoltage;
	nOut=(int)(fRightVoltage*PERIOD);
	if(nOut>1000)
	{
		nOut=1000;
	}
	ftm_pwm_duty(FTM0,FTM_CH4,nOut);//右轮正向运动PWM占空比为nOut
    }                                                     //右电机反转
}

/*!
 *  @brief      main函数
 *  @since      v5.2
 *  @note       FTM PWM 电机驱动测试
 */
void main(void)
{
    float pwmc=0;
    printf("\n*****FTM PWM 电机测试*****\n");

    ftm_pwm_init(FTM0, FTM_CH2,10*1000,0);         //初始化 FTM PWM ,使用 FTM0_CH3,频率为10k ,占空比为 100 / FTM0_PRECISON
    ftm_pwm_init(FTM0, FTM_CH3,10*1000,0);
    ftm_pwm_init(FTM0, FTM_CH4,10*1000,0);
    ftm_pwm_init(FTM0, FTM_CH5,10*1000,0);
                                                    // FTM0_PRECISON 配置 为 100 ,即占空比 为 100%
                                                    // port_cfg.h 里 配置 FTM0_CH3 对应为 PTA6
//    gpio_init(PTD15,GPO,0);                         // 使能端 输入为 0
    //山外的电机驱动模块,经过 MOS 管 反相隔离。
    //K60 输出 PWM 为 100% ,实际接入 电机驱动就是 0%
    //K60 输出 使能端 为 低电平,实际接入 电机驱动 使能端就是 高电平

    while(1)
    {
        for(pwmc=0;pwmc<1;pwmc+=0.1)
        {
          SetMotorVoltage(pwmc,pwmc);
          led (LED1,LED_ON);
          lptmr_delay_ms(1000);
          led (LED1,LED_OFF);
          lptmr_delay_ms(100);
        }
        for(pwmc=0;pwmc>-1;pwmc-=0.1)
        {
          SetMotorVoltage(pwmc,pwmc);
          led (LED1,LED_ON);
          lptmr_delay_ms(1000);
          led (LED1,LED_OFF);
          lptmr_delay_ms(100);
        }
    }
}

本文的工程文件:http://git.oschina.net/chenxuuu/K60-test/tree/master/FTM_PWM_电机驱动

K60笔记-OLED显示

本程序使用山外库:http://git.oschina.net/chenxuuu/vcan-K60-V5.3

OLED使用12864屏幕,SPI串口

必要文件:oled.coled.h

引脚定义:

  #define OLED_SCL  PTA15_OUT
  #define OLED_SDA  PTA17_OUT
  #define OLED_RST  PTA19_OUT
  #define OLED_DC   PTA16_OUT
  #define OLED_CS   PTA14_OUT
/*
4线SPI使用说明:
VBT 供内部DC-DC电压,3.3~4.3V,如果使用5V电压,为保险起见串一个100~500欧的电阻
VCC 供内部逻辑电压 1.8~6V
GND 地

BS0 低电平
BS1 低电平
BS2 低电平

CS  片选管脚
DC  命令数据选择管脚
RES 模块复位管脚
D0(SCLK) ,时钟脚,由MCU控制
D1(MOSI) ,主输出从输入数据脚,由MCU控制

D2 悬空
D3-D7 , 低电平 , 也可悬空,但最好设为低电平
RD  低电平 ,也可悬空,但最好设为低电平
RW  低电平 ,也可悬空,但最好设为低电平
RD  低电平 ,也可悬空,但最好设为低电平
*/

显示中文测试:

#include "common.h"
#include "include.h"
#include "oled.h"
uint8 testbmp[]={};//省略

void main()
{
  OLED_Init();
    while(1)
    {
       OLED_Print(0,0,"双车追不上-启动中");
       Draw_BMP(50,3,77,6,testbmp);
       while(1)
       {
       OLED_P6x8Str(10,7,"loading.  ");
       DELAY_MS(500);
       OLED_P6x8Str(10,7,"loading..  ");
       DELAY_MS(500);
       OLED_P6x8Str(10,7,"loading...");
       DELAY_MS(500);
       OLED_P6x8Str(10,7,"loading   ");
       DELAY_MS(500);
       }
    }
}

效果如下:

显示图片测试:

#include "common.h"
#include "include.h"
#include "oled.h"
uint8 bmp1[]={};//省略
uint8 bmp2[]={};//省略
uint8 bmp3[]={};//省略
uint8 bmp4[]={};//省略
void main()
{
  OLED_Init();
    while(1)
    {
       Draw_BMP(0,0,73,6,bmp1);
       DELAY_MS(500);
       Draw_BMP(0,0,73,6,bmp3);
       DELAY_MS(500);
       Draw_BMP(0,0,73,6,bmp1);
       DELAY_MS(500);
       Draw_BMP(0,0,73,6,bmp2);
       DELAY_MS(500);
       Draw_BMP(0,0,73,6,bmp1);
       DELAY_MS(500);
       Draw_BMP(0,0,73,6,bmp3);
       DELAY_MS(500);
       Draw_BMP(0,0,73,6,bmp2);
       DELAY_MS(500);
       Draw_BMP(0,0,73,6,bmp1);
       DELAY_MS(500);
       Draw_BMP(0,0,73,6,bmp4);
       DELAY_MS(500);
       Draw_BMP(0,0,73,6,bmp1);
       DELAY_MS(500);
    }
}

效果如下:

测试代码:http://git.oschina.net/chenxuuu/K60-test/tree/master/OLED