打印
[LOOK]

LOOK+红杏头文件 学习第六帖:I2C(中断方式)

[复制链接]
4334|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 hotpower 于 2011-6-19 01:23 编辑

-----------------2011-06-14---------------
在原基础上做如下调整:
① 增加main.h文件 包含所需头文件
② 继承于interrupt_t的中断抽象类I2C1_t:I2C接口的单字节及多字节的读写操作;
③ task_AT24C16_t:接收UART命令完成对AT24C16的单字节及多字节的读写操作;
   'r'为读地址0x00单字节指令、'u'为地址0x00单字节加1并存储指令、d'为地址0x00单字节减1并存储指令;
   R'为读地址0x10开始单页指令、'u'为地址0x10开始单页加1并存储指令、'D'为地址0x10开始单页减1并存储指令。


初始化设置:HCLK时钟源:外部 4~24MHz 晶振使能
                分频: 1
               I2C1时钟使能
               PA.10 PA.11配置为I2C功能


--------------------------2011-06-09---------------------------
LOOK实现四个小任务:
① task_led_t: 助学板上四个LED小灯轮流点亮,有两种显示模式,方式1为LED1--->LED2--->LED3--->LED4--->LED1循环,
                                               方式2为LED4--->LED3--->LED2--->LED1--->LED4循环,初始化为方式2;
② task_key_t: 助学板上KEY2通过查询的方式判断按下调整LED的循环方式;
③ 继承于interrupt_t的中断抽象类Key_t: 助学板上KEY1设置为下降沿中断,中断滞后服务函数内置位蜂鸣器鸣叫事件标志;
④ task_beep_t: 助学板上蜂鸣器响3声,该任务由KEY1同步。

初始化设置:时钟配置为 XTL12M_EN: 外部 4~24MHz 晶振使能
                            GPA2~5 GPB10 配置为输出模式
                            GPB14~15     配置为输入模式
            CPU时钟频率为12MHz

关于flag_t:
ANY是wait()事件标志的集合中,任何一个事件到达都可以唤醒任务,相当于“或”运算;
ALL是wait()事件标志的集合中,所有事件全部到达时才能唤醒任务,相当于“与”运算;
当期待的事件标志只有一位时,无所谓ANY,ALL。
KEEP表示到达的事件标志,在唤醒了等待的任务后,该事件不消失(可以继续唤醒其它任务);
COSUME表示到达的事件标志,在唤醒了等待的任务后,该事件消失。
--------------------------------------------------2011-06-12 AM--------------------------------------------------
在原基础上作如下调整:
① 取消中断抽象类任务Key_t,该任务实现的功能整合至一般任务类task_key_t中的key_read中;
② 增加中断抽象类任务uart0_t,该任务主要实现UART输出和接收功能,接收到字符'1'为同步蜂鸣器响3次任务,接收到字符'2'实现与KEY2按下相同功能;
③ task_beep_t中增加蜂鸣器响之前发送字符串"Buzzer rang three times!\n"。

初始化设置: PB.0选择多功能输入RXD0 PB.1选择多功能输入TXD0
            UART时钟选择外部12MHZ,并使能UART0时钟
--------------------------------------------------2011-06-12 PM--------------------------------------------------
在原基础上做如下调整:
① 增加任务类task_ad_t,完成对AD1的单次AD转换并通过串口发送转换结果;
② 使用信号灯作为在UART0接收字符'3'时AD转换任务的同步。

初始化设置:ADC时钟选择外部12MHz,分频为3 并使能ADC时钟
            PA.1配置为AD引脚功能


源程序:
main.h
#ifndef __LOOK_MAIN_H
#define __LOOK_MAIN_H

/*------------------------------------
LOOK头文件放入此处
------------------------------------*/
#include "look_config.h"
#include <look.h>
#include <instantiate>

/*------------------------------------
芯片及红杏头文件放入此处
------------------------------------*/
#include "NUC1xx.h"
#include "NUC1xxM051Seriescfg.h"

/*------------------------------------
系统定义的C++语言的头文件应该放入此处
------------------------------------*/
#include "led.h"
#include "I2C.h"

/*------------------------------------
全局类对象实例声明放入此位置
------------------------------------*/
#endif
led.h
#ifndef __LOOK_LED_H
#define __LOOK_LED_H

#define KEY_NO_DOWN ((1<<14)|(1<<15)) //无按键按下时管脚PIN值

// 任务类 task_led_t 的定义
class task_led_t : public task_t {
public:
task_led_t() __OPT_ATTR__; // 构造函数
protected:
void routine(); // 任务例程
};
// 任务类 task_led_t 的构造函数
__OPT_INLINE__ task_led_t::task_led_t()
{
// TODO: 在此初始化 task_led_t 的类成员
}


// 任务类 task_key_t 的定义
class task_key_t : public task_t {
public:
task_key_t() __OPT_ATTR__; // 构造函数
int32_t key_read() __OPT_ATTR__;
protected:
void routine(); // 任务例程
};
// 任务类 task_key_t 的构造函数
__OPT_INLINE__ task_key_t::task_key_t()
{
// TODO: 在此初始化 task_key_t 的类成员
}


// 任务类 task_beep_t 的定义
class task_beep_t : public task_t {
public:
task_beep_t() __OPT_ATTR__; // 构造函数
protected:
void routine(); // 任务例程
};
// 任务类 task_beep_t 的构造函数
__OPT_INLINE__ task_beep_t::task_beep_t()
{
// TODO: 在此初始化 task_beep_t 的类成员
}


// 任务类 task_ad_t 的定义
class task_ad_t : public task_t {
public:
task_ad_t() __OPT_ATTR__; // 构造函数
sem_t sem; // 信号灯为AD转换提供同步
protected:
void routine(); // 任务例程
};
// 任务类 task_beep_t 的构造函数
__OPT_INLINE__ task_ad_t::task_ad_t():sem(0)
{
// TODO: 在此初始化 task_ad_t 的类成员
}

// uart0_t 类为应用层提供了简单的 uart 同步输出功能及接收功能。
class uart0_t : public interrupt_t {
public:
uart0_t() __OPT_ATTR__; //构造函数
void puts(const char* str); //串口输出函数
void put_numeral(uint8_t data);
protected:
bool isr(int vector); //中断服务例程
void dsr(int vector, uintptr_t count); //中断滞后服务例程
private:
void fillfifo(const char* str); //填充FIFO
private:
const char* buffer; // 输出缓冲区
task_t* task; // 正在输出的任务
};
extern uart0_t uart0; // 创建 uart0 对象

// 任务类 task_AT24C16_t 的定义
class task_AT24C16_t : public task_t {
public:
task_AT24C16_t() __OPT_ATTR__; // 构造函数
protected:
void routine(); // 任务例程
};
// 任务类 task_beep_t 的构造函数
__OPT_INLINE__ task_AT24C16_t::task_AT24C16_t()
{
// TODO: 在此初始化 task_ad_t 的类成员
}


extern instantiate::task<task_led_t, LOOK_STACK_SIZE> task_led;
extern instantiate::task<task_key_t, LOOK_STACK_SIZE> task_key;
extern instantiate::task<task_beep_t, LOOK_STACK_SIZE> task_beep;
extern instantiate::task<task_ad_t, LOOK_STACK_SIZE> task_ad;
extern instantiate::task<task_AT24C16_t, LOOK_STACK_SIZE> task_AT24C16;

#endif
I2C.h

#ifndef __LOOK_I2C_H
#define __LOOK_I2C_H
// I2C1_t 类为应用层提供了 I2C 接口
class I2C1_t : public interrupt_t {
public:
    I2C1_t() __OPT_ATTR__;   //构造函数
    sem_t sem;      // 信号灯为AD转换提供同步
protected:
bool isr(int vector);   //中断服务例程
void dsr(int vector, uintptr_t count); //中断滞后服务例程
private://私有方法
    inline void Start(void);//复位I2C
    inline void REStart(void);//重复位I2C
//inline void Wait(void);//超时等待
inline void Exit(void);//出错退出
    inline void Stop(void);//成功结束
public://公有方法及属性
unsigned char ReadByte(unsigned int Address, unsigned char *Data);//读字节函数(方法)
unsigned char WriteByte(unsigned int, unsigned char);//写字节函数(方法)
unsigned char ReadBuffer(unsigned int, unsigned char *, unsigned int);//读块函数(方法)
unsigned char WriteBuffer(unsigned int, unsigned char *, unsigned int);//写块函数(方法)
void SetAddress(unsigned int I2CAddress);//公有只写方法(属性)
//void WriteWait(void);//EEPROM写入等待函数(方法)
unsigned int GetState(void);//公有只读方法(属性)
//void SetSystickCount(void);//公有只写方法(属性)
private://私有属性
volatile bool Busy;//忙属性
volatile unsigned int State;//私有属性
//volatile unsigned int SystickCount;//私有属性
volatile unsigned int Count;//私有属性
volatile unsigned int MainCount, SubCount;//主从计数
volatile unsigned int SubAddr;//私有属性
volatile unsigned char MainComm, SubComm;//主从通讯命令
volatile unsigned char TxBuffer[16], RxBuffer[16];//接收数据缓冲区
};
extern I2C1_t I2C_1;
#endif
工程结构截图:


工程包:
M0_LOOK_HOT.rar (834.11 KB)

相关帖子

沙发
Swallow_0322|  楼主 | 2011-6-14 17:16 | 只看该作者
本帖最后由 Swallow_0322 于 2011-6-14 17:38 编辑

源文件:
I2C.CPP

#include "main.h"

__OPT_INLINE__ I2C1_t::I2C1_t():sem(0) //构造函数
{
//I2C的引脚配置及时钟配置使用LOOK配置

SubAddr = 0xA0; //I2C设备地址
for (uint32_t i = 0; i < sizeof(TxBuffer); i ++)
{ //清空缓存
TxBuffer = 0;
RxBuffer = 0;
}
SYSCLKs.APBCLK.Bits.I2C1_EN = 1;
SYSs.IPRSTC2.Bits.I2C1_RST = 1; //I2C1模块复位
SYSs.IPRSTC2.Bits.I2C1_RST = 0; //I2C1正常工作
I2C1s.CON.Bits.ENSI = 1; //允许I2C串行功能
I2C1s.CLK.Regs = ((12000000/2*10)/(50000 * 4) + 5) / 10 - 1;
I2C1s.CON.Bits.EI = 1; //I2C1 使能中断
I2C1s.CON.Bits.STA = 0; //I2C1起始标志清零
I2C1s.CON.Bits.STO = 0; //I2C1结束标志清零
I2C1s.CON.Bits.AA = 0; //I2C1应答标志清零
I2C1s.CON.Bits.EI = 1; //I2C1 使能中断
I2C1s.CON.Bits.ENSI = 1; //允许I2C串行功能
I2C1s.CON.Bits.SI= 1; //清中断标志位

attach(I2C1_IRQn);
vector_t::enable(I2C1_IRQn);
}

// 中断服务例程
bool I2C1_t::isr(int vector)
{
bool Back_Val = FALSE;
switch(I2C1s.STATUS.Regs& 0xf8)
{
case I2C_START: //主机收到自己发送的开始信号
if (State == I2C_START) { //本次中断应该接收TW_START信号
I2C1s.DATA.Regs = SubAddr & 0xfe; //发送子机地址(写)
I2C1s.CON.Bits.STA = 0;
I2C1s.CON.Bits.SI = 1; //STA位必须清除,否则死机 清除中断标志
State = I2C_MT_SLA_ACK; //Status下次I2C_MT_SLA_ACK
}
else
{
Exit(); //通讯失败
Back_Val = TRUE;
}
break;
case I2C_REP_START: //主机收到自己发送的重新开始信号
if (State == I2C_REP_START) { //本次中断应该接收TW_RESTART信号
I2C1s.DATA.Regs = SubAddr | 0x01; //发送子机地址(读)
I2C1s.CON.Bits.STA = 0; //STA位必须清除,否则死机 清除中断标志
I2C1s.CON.Bits.SI = 1;
I2C1s.CON.Bits.AA = 1;
State = I2C_MR_SLA_ACK; //Status下次I2C_MR_SLA_ACK
}
else
{
Exit(); //通讯失败
Back_Val = TRUE;
}
break;
case I2C_MT_SLA_ACK: //主发机接收到从机的地址应答信号后发送命令
if (State == I2C_MT_SLA_ACK) { //本次中断应该接收TW_MT_SLA_ACK信号
State = I2C_MT_DATA_ACK; //Status下次应该收TW_MT_DATA_ACK
I2C1s.DATA.Regs = SubComm; //发送子机命令
I2C1s.CON.Bits.SI = 1;
I2C1s.CON.Bits.AA = 1;
}
else
{
Exit(); //通讯失败
Back_Val = TRUE;
}
break;
case I2C_MR_SLA_ACK: //主收机接收到从机的地址应答信号
if ((State == I2C_MR_SLA_ACK) && SubCount) { //本次中断应该接收TW_MR_SLA_ACK信号
State = I2C_MR_DATA_ACK; //Status下次应该收TW_MR_DATA_ACK
I2C1s.CON.Bits.SI = 1;
I2C1s.CON.Bits.AA = 1;
}
else
{
Exit(); //通讯失败
Back_Val = TRUE;
}
break;
case I2C_MT_DATA_ACK: //主收机接收到从机的数据应答信号
if ((State == I2C_MT_DATA_ACK) && (Count < MainCount)) {//本次中断应该接收TW_MT_DATA_ACK信号
I2C1s.DATA.Regs = TxBuffer[Count ++];//发送子机数据
I2C1s.CON.Bits.SI = 1;
I2C1s.CON.Bits.AA = 1;
}
else {
if ((State == I2C_MT_DATA_ACK) && (Count == MainCount) && (SubAddr & 1)) {//本次中断应该接收TW_MT_DATA_ACK信号
REStart();//
}
else
{
Stop(); //通讯成功
Back_Val = TRUE;
}
}
break;
case I2C_MR_DATA_ACK:
if ((State == I2C_MR_DATA_ACK) && (Count < SubCount)) {
RxBuffer[Count ++] = I2C1s.DATA.Regs;//接收子机数据
if (Count < SubCount) {
I2C1s.CON.Bits.SI = 1;
I2C1s.CON.Bits.AA = 1;
}
else {
I2C1s.CON.Bits.AA = 0;
I2C1s.CON.Bits.SI = 1;
State = I2C_MR_DATA_NACK;//下次进入I2C_MR_DATA_NACK,接收数据准备完成
}
}
else
{
Exit(); //通讯失败
Back_Val = TRUE;
}
break;
case I2C_MR_DATA_NACK: //数据接收结束
if ((State == I2C_MR_DATA_NACK) && (Count == SubCount)) {
Stop(); //通讯成功
}
else Exit(); //通讯失败
Back_Val = TRUE;
break;
// case I2C_MT_DATA_NACK:
// Exit();//通讯失败
// break;
default:
Exit(); //通讯失败
Back_Val = TRUE;
break;
}
return Back_Val;
}

// 中断滞后服务例程
void I2C1_t::dsr(int vector, uintptr_t count)
{
sem.do_post(); //释放一个信号量资源
}


void I2C1_t::Start(void)
{
Busy = true;
State = I2C_START; //主机准备发送启始位
Count = 0; //发送数据个数
//SystickCount = 0; //清除节拍计数器
I2C1s.CON.Bits.STO = 0; //I2C1结束标志清零
I2C1s.CON.Bits.AA = 0; //I2C1应答标志清零
I2C1s.CON.Bits.EI = 1; //I2C1 使能中断
I2C1s.CON.Bits.ENSI = 1; //允许I2C串行功能
I2C1s.CON.Bits.SI= 1; //清中断标志位
I2C1s.CON.Bits.STA = 1; //I2C1起始标志置位
//delay(LOOK_TICKS_PER_SEC);
while(!sem.wait());
// task = &scheduler.get_current_task();
// delay(); // 阻塞任务
}

void I2C1_t::REStart(void)
{
Busy = true;
State = I2C_REP_START; //主机准备发送启始位
Count = 0; //发送数据个数
I2C1s.CON.Bits.STA = 1; //I2C1起始标志置位
I2C1s.CON.Bits.SI= 1; //清中断标志位*/
}

void I2C1_t::Stop(void)
{
Busy = false;
State = I2C_BUS_OK;//通讯成功
I2C1s.CON.Bits.STO = 1; //I2C1结束标志置位
I2C1s.CON.Bits.SI = 1; //清中断标志位*/
}

void I2C1_t::Exit(void)
{
Busy = false;
State = I2C_BUS_ERROR; //通讯失败
I2C1s.CON.Bits.STO = 1; //I2C1结束标志置位
I2C1s.CON.Bits.SI = 1; //清中断标志位
}

unsigned char I2C1_t::ReadByte(unsigned int Address, unsigned char *Data)
{
SubAddr |= 0x01;
MainCount = 0; //发送0个数据(只读)
//本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
SubComm = Address; //读出地址
SubCount = 1; //接收1个数据
//SystickCount = 0;
Start(); //启动I2C模块
if (State == I2C_BUS_OK)
{
//通讯成功
Data[0] = RxBuffer[0]; //从接收缓冲区取出一个字节
}
return State; //(读出数据在RxBuffer[0]~RxBuffer[15])
}

unsigned char I2C1_t::WriteByte(unsigned int Address, unsigned char Data)
{
SubAddr &= 0xfe;
MainCount = 1; //发送1个数据
//本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
SubComm = Address; //写入地址
TxBuffer[0] = Data; //写入1个数据到发送缓冲区
SubCount = 0; //接收0个数据
Start(); //启动I2C模块
delay(LOOK_TICKS_PER_SEC/10); //延时100mS等待写入完成
return State;
}

unsigned char I2C1_t::ReadBuffer(unsigned int Address, unsigned char *Data, unsigned int Cnt)
{
SubAddr |= 0x01;
MainCount = 0;//发送0个数据(只读)
//本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
SubComm = Address;//读出地址
SubCount = (Cnt <= sizeof(RxBuffer)) ? Cnt : sizeof(RxBuffer);//接收Cnt个数据
Start();//启动I2C模块
if (State == I2C_BUS_OK) {//通讯成功
for (uint8_t i = 0; i < SubCount; i ++) Data = RxBuffer;//从接收缓冲区取出Cnt个字节
}
return State;//(读出数据在RxBuffer[0]~RxBuffer[15])
}

unsigned char I2C1_t::WriteBuffer(unsigned int Address, unsigned char *Data, unsigned int Cnt)
{
SubAddr &= 0xfe;
MainCount = (Cnt <= sizeof(TxBuffer)) ? Cnt : sizeof(TxBuffer);//发送Cnt个数据
//本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
SubComm = Address;//写入地址
for (uint8_t i = 0; i < MainCount; i ++) TxBuffer = Data;//写入Cnt个数据到发送缓冲区
SubCount = 0;//接收0个数据
Start();//启动I2C模块
delay(LOOK_TICKS_PER_SEC/10); //延时100mS等待写入完成
return State;
}


unsigned int I2C1_t::GetState(void)
{
return State;
}

void I2C1_t::SetAddress(unsigned int I2CAddress)
{
SubAddr = I2CAddress;
}

/*void I2cObj::SetSystickCount(void)
{
SystickCount ++;
}*/

I2C1_t I2C_1;


led.cpp
 
#include "main.h"
flag_t Flag(0);  //位0为LED闪烁模式  位1为KEY1控制蜂鸣器任务同步标志   位2为UART通信控制蜂鸣器任务同步标志
flag_t Flag_I2C(0);  //通过I2C读写AT24c16同步标志
// uart0 构造函数
__OPT_INLINE__ uart0_t::uart0_t()
{
    attach(UART0_IRQn);
    vector_t::enable(UART0_IRQn);
    SYSs.IPRSTC2.Bits.UART0_RST = 1;  //UART0 模块复位
    SYSs.IPRSTC2.Bits.UART0_RST = 0;  //UART0 模块正常工作
    UART0s.FCR.Bits.TFR = 1;    //TX 软件复位
    UART0s.FCR.Bits.RFR = 1;    //RX 软件复位
    UART0s.FCR.Bits.RFITL = 0x00;   //Rx FIFO中断 (INT_RDA) 触发级别   1位
   
UART0s.LCR.Bits.SPE = 0;    //无校验  奇偶使能位
UART0s.LCR.Bits.EPE = 0;                //  0----奇校验 1----偶校验
UART0s.LCR.Bits.PBE = 0;   
    UART0s.LCR.Bits.WLS = 0b011;   //字长度选择 8bits
    UART0s.LCR.Bits.NSB = 0;    //1位停止位
   
UART0s.BAUD.Bits.BRD = 0x66;   //外部12MHz 115200bps  对波特率分频寄存器的设置波特率分频设置即该句必须放在第一位
UART0s.BAUD.Bits.DIV_X_EN = 1;   //使能分频X
UART0s.BAUD.Bits.DIV_X_ONE = 1;   //Divider X equal 1
UART0s.IER.Bits.RDA_IEN = 1;   //使能接收中断
    /*
     DIV_X_EN  DIV_X_ONE  Divider X  BRD  波特率公式
Disable       0         B        A   UART_CLK / [16 * (A+2)]
Enable        0         B        A   UART_CLK / [(B+1) * (A+2)] , B must >= 8
Enable        1         B        A   UART_CLK / (A+2), A must >=3
*/
}
// uart0 输出
void uart0_t::puts(const char* str)
{
    fillfifo(str);                  // 填充 fifo
    UART0s.IER.Bits.THRE_IEN = 1;   // 允许发送中断
    task = &scheduler.get_current_task();
    delay();                        // 阻塞任务
}
void uart0_t::put_numeral(uint8_t data)
{
char str[2];
char *p;
str[0] = ((data/16%16>9)?(data/16%16+'A'-10)data/16%16+'0'));
str[1] = ((data%16>9)?(data%16+'A'-10)data%16+'0'));
p = &str[0];
puts(p);
}
// uart0 中断服务例程
bool uart0_t::isr(int vector)
{
if (UART0s.ISR.Bits.THRE_INT==1)
{
  //UART0发送中断
     const char* str = buffer;
     if (str == 0) {                     // 无数据
         UART0s.IER.Bits.THRE_IEN = 0;   // 禁止发送中断
         return true;
     }
     fillfifo(str);                      // 填充 fifo
     return false;
}
if (UART0s.ISR.Bits.RDA_INT==1)
{
  //UART0接收中断
  /* Get all the input characters */
  while(UART0s.ISR.Bits.RDA_IF)
  {
   /* Get the character from UART Buffer */
   char Received_Data = UART0s.DATA.Regs;
   switch (Received_Data)
   {
    case '1':
     //执行蜂鸣器响3次的任务
     Flag.do_set_bits(0b0100);
     break;
    case '3':
     task_ad.sem.do_post();   //释放一个信号量资源
     break;
    case 'R':
     Flag_I2C.do_set_bits(0b01);
     break;
    case 'r':
     Flag_I2C.do_set_bits(0b010);
     break;
    case 'U':
     Flag_I2C.do_set_bits(0b0100);
     break;
    case 'u':
     Flag_I2C.do_set_bits(0b01000);
     break;
    case 'D':
     Flag_I2C.do_set_bits(0b010000);
     break;
    case 'd':
     Flag_I2C.do_set_bits(0b0100000);
     break;
    case '2':
     //执行与KEY2相同的动作
     int ** = Flag.peek();
       if (**&0b01)
         Flag.do_mask_bits(~0b01);  //清除事件标志 位0
        else
         Flag.do_set_bits(0b01);  //置位事件标志 位0
        break;
   }
   return false;
  }
}
return false;
}
// uart0 中断滞后服务例程
// 所有数据发送完成后,dsr() 被调用
void uart0_t::dsr(int vector, uintptr_t count)
{
    task->do_wakeup();              // 唤醒任务
}
// uart0 填充 fifo
void uart0_t::fillfifo(const char* str)
{
    do {
        char ch;
        ch = *str++;
        if (ch == 0) {
            str = 0;
            break;
        }
        UART0s.DATA.Regs = ch;
    } while (!UART0s.FSR.Bits.TX_FULL);
    buffer = str;
}
uart0_t uart0;              // 创建 uart0 对象
// 任务类 task_led_t 的例程
void task_led_t::routine()
{
// TODO: 在此编写 task_led_t 例程的内容
GPIOAs.DMASK.Regs = ~0b111100;
GPIOAs.DOUT.Regs = ~0b100;
while (true)
{
   // TODO: 在此编写 task_led_t 例程的内容
    uint32_t data = GPIOAs.DOUT.Regs & 0b111100;
    int flag = Flag.peek();
    if (flag)
    {
      data <<= 1;
      data += data >> 4;
    }
    else
    {
      data >>= 1;
      data += data << 4;
    }
    GPIOAs.DOUT.Regs = data;
    delay(LOOK_TICKS_PER_SEC/2);
}
}
// 任务类 task_key_t 的例程
void task_key_t::routine()
{
// TODO: 在此编写 task_key_t 例程的内容
while (true)
{
    // TODO: 在此编写 task_key_t 例程的内容
    uint32_t Key_Val = key_read();
  if ((Key_Val&(1<<14))==0)
  {
   //KEY2 按下
   int ** = Flag.peek();
     if (**&0b01)
       Flag.mask_bits(~0b01);  //清除事件标志 位0
      else
       Flag.set_bits(0b01);  //置位事件标志 位0
  }
  if ((Key_Val&(1<<15))==0)
  {
   //KEY1 按下
   Flag.do_set_bits(0b010);
  }
    delay(LOOK_TICKS_PER_SEC/10);
}
}
// 任务类 task_key_t 的成员函数
__OPT_INLINE__ int32_t task_key_t::key_read()
{
uint32_t Key_Tmp = TRUE;
static uint32_t Key_Record = KEY_NO_DOWN;   //按键记录
Key_Tmp = GPIOBs.PIN.Regs&KEY_NO_DOWN;
if(Key_Tmp==KEY_NO_DOWN)          //无有效按键按下
{
   Key_Record = KEY_NO_DOWN;     //清除按键记录
    return KEY_NO_DOWN;          //程序退出
}
if(Key_Record!=Key_Tmp)         //为新按键
{
    Key_Record = Key_Tmp;        //保存本次结果
    delay(LOOK_TICKS_PER_SEC/100);    //延时去抖动
    Key_Tmp = GPIOBs.PIN.Regs&KEY_NO_DOWN;
    if(Key_Tmp==Key_Record)
    return Key_Tmp;
}
return KEY_NO_DOWN;
}
// 任务类 task_beep_t 的例程
void task_beep_t::routine()
{
// TODO: 在此编写 task_beep_t 例程的内容
    GPIOBs.DOUT.Bits.Pin10 = 0;     //蜂鸣器不响
while (true)
{
    // TODO: 在此编写 task_beep_t 例程的内容
    int flag = Flag.wait(0b110, flag_t::ANY_CONSUME);  
     if (flag)
     {
      uart0.puts("Buzzer rang three times!\n");
        for (uint32_t i = 0; i < 6; i ++)
      {  
    //蜂鸣器响三次
          GPIOBs.DOUT.Bits.Pin10 ^= 1;   //蜂鸣器响PB10=1,不响PB10=0
              delay(LOOK_TICKS_PER_SEC);   //断续间隔
      }
      }
}
}   
// 任务类 task_ad_t 的例程
void task_ad_t::routine()
{
// TODO: 在此编写 task_ad_t 例程的内容
SYSs.IPRSTC2.Bits.ADC_RST = 1;
SYSs.IPRSTC2.Bits.ADC_RST = 0;  /* Reset ADC */
//ADC时钟、分频及配置为AD引脚在look中配置
ADCs.ADCR.Bits.ADEN = 1;   //使能AD模块
ADCs.ADCALR.Bits.CALEN = 1;   //自校正使能
while(!ADCs.ADCALR.Bits.CALDONE); //等待自校正结束
ADCs.ADCR.Bits.DIFFEN = 0;   //单端输入
ADCs.ADCR.Bits.ADST = 0;   //停止AD
ADCs.ADCR.Bits.ADMD = 0;   //单一转换
ADCs.ADCHER.Bits.CHEN = 0x02;  //模拟输入通道1使能
ADCs.ADSR.Bits.ADF = 1;    //清AD中断标志
while (true)
{
    // TODO: 在此编写 task_ad_t 例程的内容
  if (sem.wait())
  {
   ADCs.ADCR.Bits.ADST = 1; //启动AD
   while(!ADCs.ADSR.Bits.ADF); //等待转换结束
   ADCs.ADSR.Bits.ADF = 1;  //清AD中断标志
   uint32_t AD_Result = ADCs.ADDR1.Regs&0xFFF;
   char str[4];
   char *p;
   str[0] = AD_Result/1000+'0';
   str[1] = AD_Result/100%10+'0';
   str[2] = AD_Result/10%10+'0';
   str[3] = AD_Result%10+'0';
   p = &str[0];
   uart0.puts("ADC_RESULT_AD1:");
   uart0.puts(p);
  }
  
}
}
// 任务类 task_AT24C16_t 的例程
void task_AT24C16_t::routine()
{
// TODO: 在此编写 task_beep_t 例程的内容
uint8_t EEPROM_Data = 0;  //IIC地址0x00读写数据
uint8_t I2C_Page_Test[16];  //IIC地址0x10页读写数据
uint8_t i = 0;
while (true)
{
    // TODO: 在此编写 task_beep_t 例程的内容
    //uint8_t ** = Flag_I2C.peek();
    int flag = Flag_I2C.wait(0b0111111, flag_t::ANY_CONSUME);
     switch (flag)
     {
      case 0x01:
    if (I2C_BUS_OK==I2C_1.ReadBuffer(0x10,I2C_Page_Test,16))
    {
     uart0.puts("\nAT24C16地址0x10开始16字节的内容为:\n");
     for (i=0;i<16;i++)
      uart0.put_numeral(I2C_Page_Test);
    }
    else
     uart0.puts("\nAT24C16地址0x10开始16字节的内容读取失败!");
    break;
   case 0x02:
    if (I2C_BUS_OK==I2C_1.ReadByte(0x00,&EEPROM_Data))
    {
     uart0.puts("\nAT24C16地址0的内容为:0x");
     uart0.put_numeral(EEPROM_Data);
    }
    else
     uart0.puts("\nAT24C16地址0的内容读取失败!");
    break;
   case 0x04:
    for (i=0;i<16;i++)
     I2C_Page_Test++;
    if (I2C_BUS_OK==I2C_1.WriteBuffer(0x10,I2C_Page_Test,16))
     uart0.puts("\nAT24C16地址0x10开始16字节的内容加1成功!");
    else
    {
     uart0.puts("\nAT24C16地址0x10开始16字节的内容加1失败!");
     for (i=0;i<16;i++)
      I2C_Page_Test--;
    }
    break;
   case 0x08:
    if (I2C_BUS_OK==I2C_1.WriteByte(0x00,++EEPROM_Data))
     uart0.puts("\nAT24C16地址0的内容加1成功!");
    else
     uart0.puts("\nAT24C16地址0的内容加1失败!");
    break;
   case 0x10:
    for (i=0;i<16;i++)
     I2C_Page_Test--;
    if (I2C_BUS_OK==I2C_1.WriteBuffer(0x10,I2C_Page_Test,16))
     uart0.puts("\nAT24C16地址0x10开始16字节的内容减1成功!");
    else
    {
     uart0.puts("\nAT24C16地址0x10开始16字节的内容减1失败!");
     for (i=0;i<16;i++)
      I2C_Page_Test++;
    }
    break;
   case 0x20:
    if (I2C_BUS_OK==I2C_1.WriteByte(0x00,--EEPROM_Data))
     uart0.puts("\nAT24C16地址0的内容减1成功!");
    else
     uart0.puts("\nAT24C16地址0的内容减1失败!");
    break;
    default:
     uart0.puts("\nAT24C16读写操作错误!");
        }
    }
}  
#ifdef LOOK_SCHEDULING_PRIORITY
instantiate::task<task_key_t, LOOK_STACK_SIZE> task_key(0);
instantiate::task<task_beep_t, LOOK_STACK_SIZE> task_beep(3);
instantiate::task<task_led_t, LOOK_STACK_SIZE> task_led(2);
instantiate::task<task_ad_t, LOOK_STACK_SIZE> task_ad(1);
instantiate::task<task_AT24C16_t, LOOK_STACK_SIZE> task_AT24C16(4);
#else
instantiate::task<task_key_t, LOOK_STACK_SIZE> task_key;
instantiate::task<task_beep_t, LOOK_STACK_SIZE> task_beep;
instantiate::task<task_led_t, LOOK_STACK_SIZE> task_led;
instantiate::task<task_ad_t, LOOK_STACK_SIZE> task_ad;
instantiate::task<task_AT24C16_t, LOOK_STACK_SIZE> task_AT24C16;
#endif

使用特权

评论回复
板凳
hotpower| | 2011-6-14 19:22 | 只看该作者
挺好的,多任务呀,adc,uart,iic,gpio

使用特权

评论回复
地板
Cube| | 2011-6-14 19:25 | 只看该作者
沙发没了。。。

使用特权

评论回复
5
Swallow_0322|  楼主 | 2011-6-14 19:25 | 只看该作者
呵呵 都是简单的应用 任务的关联不大

使用特权

评论回复
6
weshiluwei6| | 2011-6-14 19:26 | 只看该作者
太牛了太牛了太牛了 太牛了

使用特权

评论回复
7
hotpower| | 2011-6-14 20:40 | 只看该作者
水王考试完了就look

使用特权

评论回复
8
hotpower| | 2011-6-16 08:30 | 只看该作者
刚运行了三心的例程,很不错!https://bbs.21ic.com/icview-242344-1-1.html

使用特权

评论回复
9
hotpower| | 2011-6-16 11:51 | 只看该作者
运行了,很不错!
初始化蜂鸣器输出为0就好了。

使用特权

评论回复
10
Swallow_0322|  楼主 | 2011-6-16 14:07 | 只看该作者
本帖最后由 Swallow_0322 于 2011-6-16 14:08 编辑

多谢大叔关注!
现在蜂鸣器的控制初始化就是0啊,您运行有问题吗?

// 任务类 task_beep_t 的例程
void task_beep_t::routine()
{
    // TODO: 在此编写 task_beep_t 例程的内容
    GPIOBs.DOUT.Bits.Pin10 = 0;     //蜂鸣器不响
while (true)
{
    // TODO: 在此编写 task_beep_t 例程的内容
    int flag = Flag.wait(0b110, flag_t::ANY_CONSUME);  
     if (flag)
     {
      uart0.puts("Buzzer rang three times!\n");
        for (uint32_t i = 0; i < 6; i ++)
      {  
          //蜂鸣器响三次
          GPIOBs.DOUT.Bits.Pin10 ^= 1;   //蜂鸣器响PB10=1,不响PB10=0
           delay(LOOK_TICKS_PER_SEC);   //断续间隔
      }
      }
}
}  

使用特权

评论回复
11
hotpower| | 2011-6-16 21:22 | 只看该作者
void task_beep_t::routine()

{

    // TODO: 在此编写 task_beep_t 例程的内容

    GPIOBs.DOUT.Bits.Pin10 = 0;     //蜂鸣器不响



这个有点慢,也可能是我设置了断点。
在老师的配置向导里要关掉快的多。
例程必须这个任务在运行状态,故初始化应该在其构造函数里面

使用特权

评论回复
12
hotpower| | 2011-6-17 11:37 | 只看该作者
今晚我想讲讲这个例程,不知道我理解正确否。
最近问iic的问题很多,刚好用这个例程讲讲。
三心的iic做了三个了,我在群里有2个。

使用特权

评论回复
13
Swallow_0322|  楼主 | 2011-6-17 19:01 | 只看该作者
void task_beep_t::routine()

{

    // TODO: 在此编写 task_beep_t 例程的内容

    GPIOBs.DOUT.Bits.Pin10 = 0;     //蜂鸣器不响



这个有点慢,也可能是我设置了断点。
在老师的配置向导里要关掉快的多。
例 ...
hotpower 发表于 2011-6-16 21:22

哦 知道了  多谢大叔指导!

使用特权

评论回复
14
Swallow_0322|  楼主 | 2011-6-17 19:03 | 只看该作者
12# hotpower

强烈支持!
这周一直在忙,SPI的例程还需稍推迟些!

使用特权

评论回复
15
hotpower| | 2011-6-17 19:21 | 只看该作者
知道了,以后你写笔记,俺评述~~~

使用特权

评论回复
16
plc_avr| | 2011-6-17 19:34 | 只看该作者
支持三心!多出笔记..........嘿嘿。

使用特权

评论回复
17
Swallow_0322|  楼主 | 2011-6-18 07:31 | 只看该作者
15# hotpower

谢谢大叔的支持,一定努力!

使用特权

评论回复
18
Swallow_0322|  楼主 | 2011-6-18 07:32 | 只看该作者
16# plc_avr

多谢烈火支持,多多指教!

使用特权

评论回复
19
hotpower| | 2011-6-18 07:41 | 只看该作者
感觉以后要多讲讲笔记

使用特权

评论回复
20
Swallow_0322|  楼主 | 2011-6-18 14:04 | 只看该作者
19# hotpower

支持!
最好对笔记内容提出些建议,作为对作笔记者的一种奖励,呵呵!
:P

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:播种一种行为,收获一种习惯;播种一种习惯,收获一种性格;播种一种性格,收获一种人生!

121

主题

1393

帖子

4

粉丝