本帖最后由 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
|