📄 main.cpp
字号:
//inline
void UartObj::putchar(unsigned char dat)
{
U0->THR = dat;
while ((U0->LSR & (1 << TEMT)) == 0);// 等待数据发送完毕
}
//inline
void UartObj::putstr(const char str[])
{
while (*str) {
putchar(*str);
str++;
}
}
//inline
void UartObj::puts(const char str[])
{
while (*str) {
putchar(*str);
str++;
}
putchar(0x0d);
putchar(0x0a);//回车换行
}
//__inline
TwiObj::TwiObj(void)
{
TwiInit();
}
void TwiObj::TwiInit(void)
{
PINSEL->PIN_SEL0 |= (P0_2_SCL0 << P0_2_PINSEL) | (P0_3_SDA0 << P0_3_PINSEL);
I2C0->I2C_CONCLR = (1 << STAC) | (1 << SIC) | (1 << AAC);
// I2CPORT->IODIR |= (1 << SDA) | (1 << SCL);
// I2CPORT->IOSET = (1 << SDA);
// I2CPORT->IOSET = (1 << SCL);
I2C0->I2C_SCLH = (Fpclk / Fi2c + 1) /2;
I2C0->I2C_SCLL = (Fpclk / Fi2c) /2;
I2C0->I2C_CONCLR = (1 << STA) | (1 << SI);
I2C0->I2C_CONSET = (1 << I2EN);
Count = 0;
}
void TwiObj::TWStart(void)
{
Busy = true;
Status = 0;//主机准备发送启始位
Count = 0;//发送数据个数
I2C0->I2C_CONSET = (1 << I2EN) | (1 << STA);
}
void TwiObj::TWREStart(void)
{
Busy = true;
Status = 0x55;//主机准备发送启始位
Count = 0;//接收数据个数
I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);
I2C0->I2C_CONSET = (1 << I2EN) | (1 << STA);
}
//__inline
void TwiObj::TWStop(void)
{
Busy = false;
Status = 0x88;//通讯成功
I2C0->I2C_CONSET = (1 << I2EN) | (1 << STO);
I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);
}
void TwiObj::TWExit(void)
{
Busy = false;
I2C0->I2C_CONSET = (1 << I2EN) | (1 << STO);
I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);
}
void TwiObj::Exec(void)
{
//char str[64];
//int I2C_STAT;
//I2C_STAT = I2C0->I2C_STAT;
switch(I2C0->I2C_STAT & 0xf8) {//测试5位状态码
case I2C_START://主机收到自己发送的开始信号
if (Status == 0) {//本次中断是在调用TWStart()函数后引发的
I2C0->I2C_DAT = SubAddr & 0xfe;//发送从机机地址(强行设置写操作)
Status = 1;//Status下次主发为1,主收为2。准备进入主发模式
I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//清除中断标志
}
else TWExit();//本次中断不是在调用TWStart()函数后引发的
break;
case I2C_REP_START://主机收到自己发送的重新开始信号
if ((Status == 0x55) && (SubAddr & 0xfe)) {//本次中断是在调用TWREStart()函数后引发的
I2C0->I2C_DAT = SubAddr;//发送从机地址(本次中断必须是读操作)
Status = 2;//Status下次主发为1,主收为2。准备进入主收模式
I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//清除中断标志
}
else TWExit();//本次中断不是在调用TWREStart()函数或不为读操作后引发的
break;
case I2C_MT_SLA_ACK://主发机接收到从机的地址应答信号后发送命令
if (Status == 1) {//本次中断应该在发送从机地址写操作后引发
Status = 3;//Status下次应该收TW_MT_DATA_ACK
I2C0->I2C_DAT = SubComm;//发送子机命令
I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//清除中断标志
}
else TWExit();//本次中断不是在发送从机地址写操作后引发
break;
case I2C_MR_SLA_ACK://主收机接收到从机的地址应答信号
if (SubCount && (Status == 2)) {//本次中断应该接收I2C_MR_SLA_ACK信号
Status = 4;//Status下次应该收I2C_MR_DATA_ACK
I2C0->I2C_CONCLR = (1 << STA) | (1 << SI);//清除中断标志
I2C0->I2C_CONSET = (1 << AA);//主机向从机发送应答信号?????????
}
else TWExit();
break;
case I2C_MT_DATA_ACK:
if ((Count < MainCount) && (Status == 3)) {//本次中断应该接收TW_MT_DATA_ACK信号
// if ((Count < MainCount) && (Status == 3) && ((SubAddr & 1) == 0)) {//本次中断应该接收TW_MT_DATA_ACK信号
I2C0->I2C_DAT = TxBuffer[Count ++];//发送子机数据
I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//清除中断标志
}
else {
if ((SubCount > 0) && (Status == 3) && (SubAddr & 1)) {//本次中断应该接收TW_MT_DATA_ACK信号
TWREStart();//
// Uart.puts("TWREStart()");
}
else TWExit();
}
break;
// case I2C_MT_DATA_NACK://数据发送结束
// if ((Count == MainCount) && (Status == 4)) {
// TW_Error = 0xf0;//数据发送失败
// }
// TWStop();
// break;
case I2C_MR_DATA_ACK:
if ((Count < SubCount) && (Status == 4)) {
RxBuffer[Count ++] = I2C0->I2C_DAT;//接收子机数据
if (Count < SubCount) {
I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//主机转入接收状态
I2C0->I2C_CONSET = (1 << AA);//主机向从机发送应答信号
}
else {//最后一个接收数据主机不向从机发送应答信号
I2C0->I2C_CONCLR = (1 << STA) | (1 << SI) | (1 << AA);//清除中断标志,主机转入接收状态
}
// sprintf(str, "RxBuffer[%02d]=%02X", Count - 1, RxBuffer[Count - 1]);
// Uart.puts(str);
}
else TWExit();
break;
case I2C_MR_DATA_NACK://数据接收结束
if ((Count == SubCount) && (Status == 4)) {
TWStop();//正常结束
// Uart.puts("TWStop()");
}
else TWExit();
break;
default://其他状态认为通讯失败
TWExit();
}
// sprintf(str, "I2C0->I2C_STAT=%02X TWIStatus=%04d Count=%04d", I2C_STAT, Status, Count);
// Uart.puts(str);
}
void TwiObj::TWByteWrite(unsigned int addr, unsigned int cnt)
{
MainCount = cnt;//发送数据
SubCount = 0;//接收数据
SubComm = addr;
SubAddr = 0xa1;
TWStart();
while (Busy);
}
void TwiObj::TWByteRead(unsigned int addr, unsigned int cnt)
{
MainCount = 0;//发送数据
SubCount = cnt;//接收数据
SubComm = addr;
SubAddr = 0xa1;
TWStart();
while(Busy);
}
void TwiObj::WorkExec(void)
{
for(int i = 0; i < 16;i ++) {
TxBuffer[i] = 16 + i;
}
SubCount = 0;//接收0个数据
MainCount = 0;//发送0个数据
SubComm = 0;
if (Busy) {
TWStop();
//::Uart.puts("TW_Busy");
}
else {
//
SubAddr = 0xa1;
SubCount = 10;//接收4个数据
SubComm = 0;
MainCount = 6;//10;//发送0个数据
for(int i = 0; i < 10;i ++) {
RxBuffer[i] = 0;
}
//
/*
I2C0->I2C_STAT=08 TWIStatus=0001 Count=0000
I2C0->I2C_STAT=18 TWIStatus=0003 Count=0000
TWREStart()
I2C0->I2C_STAT=28 TWIStatus=0085 Count=0000
I2C0->I2C_STAT=10 TWIStatus=0002 Count=0000
I2C0->I2C_STAT=40 TWIStatus=0004 Count=0000
I2C0->I2C_STAT=50 TWIStatus=0004 Count=0001
I2C0->I2C_STAT=50 TWIStatus=0004 Count=0002
I2C0->I2C_STAT=50 TWIStatus=0004 Count=0003
I2C0->I2C_STAT=50 TWIStatus=0004 Count=0004
I2C0->I2C_STAT=50 TWIStatus=0004 Count=0005
I2C0->I2C_STAT=50 TWIStatus=0004 Count=0006
I2C0->I2C_STAT=50 TWIStatus=0004 Count=0007
I2C0->I2C_STAT=50 TWIStatus=0004 Count=0008
I2C0->I2C_STAT=50 TWIStatus=0004 Count=0009
I2C0->I2C_STAT=50 TWIStatus=0004 Count=0010
I2C0->I2C_STAT=58 TWIStatus=0004 Count=0010
*/
//////////////////////////////////////////
/*
SubAddr = 0xa0;
SubCount = 0;//接收4个数据
SubComm = 0;//字节地址
MainCount = 10;//10;//发送0个数据
for(int i = 0; i < 10;i ++) {
TxBuffer[i] = 10 + i;
}
*/
/*
I2C0->I2C_STAT=08 TWIStatus=0001 Count=0000
I2C0->I2C_STAT=18 TWIStatus=0003 Count=0000
I2C0->I2C_STAT=28 TWIStatus=0003 Count=0001
I2C0->I2C_STAT=28 TWIStatus=0003 Count=0002
I2C0->I2C_STAT=28 TWIStatus=0003 Count=0003
I2C0->I2C_STAT=28 TWIStatus=0003 Count=0004
I2C0->I2C_STAT=28 TWIStatus=0003 Count=0005
I2C0->I2C_STAT=28 TWIStatus=0003 Count=0006
I2C0->I2C_STAT=28 TWIStatus=0003 Count=0007
I2C0->I2C_STAT=28 TWIStatus=0003 Count=0008
I2C0->I2C_STAT=28 TWIStatus=0003 Count=0009
I2C0->I2C_STAT=28 TWIStatus=0003 Count=0010
I2C0->I2C_STAT=28 TWIStatus=0003 Count=0010
*/
//////////////////////////////////////////
// SubAddr = 0xa1;
// SubCount = 10;//接收4个数据
// SubComm = 1;
// MainCount = 10;//10;//发送0个数据
TWStart();
}
}
IapObj::IapObj(void)
{
IapInit();
// IapWriteTest();
}
void IapObj::IapInit(void)
{
}
void IapObj::IapWriteTest(void)
{
char str[64];
unsigned char a[256];//ram
unsigned char *ptr;
int i;
ptr = (unsigned char *)0x000010000;//flash
Uart.puts("");
if (EraseSector(ptr, (void *)0x000100ff)) {
Uart.puts("擦除成功!!!");
}
else {
Uart.puts("擦除失败!!!");
}
for (i = 0; i < 256; i ++) {
a[i] = *(ptr + i);
}
// for (i = 128; i < 256; i ++) {
// a[i] = (unsigned char)i;
// }
Uart.puts("");
for (i = 0; i < 256; i ++) {
a[i] = (unsigned char)i;
if (ProgramPage(ptr, (void *)&a[0], 256)){
sprintf(str, "%02X -->一次写入成功!!!", i);
Uart.puts(str);
}
else {
sprintf(str, "%02X -->一次写入失败!!!", i);
Uart.puts(str);
}
}
Uart.puts("");
for (i = 0; i < 256; i ++) {
sprintf(str, "%02X: %02X", i, *(ptr + i));
Uart.puts(str);
}
Uart.puts("");
for (i = 0; i < 4; i ++) {//对0xfe进行二次写入,写4遍后为0xaa
a[254] &= ~(1 << (i * 2));
if (ProgramPage(ptr, (void *)&a[0], 256)){
sprintf(str, "%02X -->二次写入成功!!!", a[254]);
Uart.puts(str);
}
else {
sprintf(str, "%02X -->二次写入失败!!!", a[254]);
Uart.puts(str);
}
}
Uart.puts("");
for (i = 0; i < 8; i ++) {//对0xff进行二次写入,写8遍后为0x00
// a[255] &= ~(1 << i);//等效为下句
a[255] <<= 1;
if (ProgramPage(ptr, (void *)&a[0], 256)){
sprintf(str, "%02X -->二次写入成功!!!", a[255]);
Uart.puts(str);
}
else {
sprintf(str, "%02X -->二次写入失败!!!", a[255]);
Uart.puts(str);
}
}
}
typedef void (* IAPPV)(LPCS_IAPDATA &, unsigned int *);//一般函数指针
#define IAP_ENTER_ADR 0x7FFFFFF1 // IAP入口地址定义
bool IapObj::IapExec(void)
{
unsigned int save_VicInt; // for saving of interrupt enable register
bool result;
/* 定义函数指针 */
//void (*IAP_Entry)(LPCS_IAPDATA &);
save_VicInt = VIC->IntEnable; // save interrupt enable status
VIC->IntEnClr = 0xFFFFFFFF; // disable all interrupts
IAPPV IAP_Entry = reinterpret_cast<IAPPV>(IAP_ENTER_ADR);
IAP_Entry(IAPDR, &IAPDR.stat);// 调用IAP服务程序
// iap_execute(IAPDR);// 调用IAP服务程序
VIC->IntEnable = save_VicInt; // enable interrupts
result = (IAPDR.stat == CMD_SUCCESS);
return result;
}
unsigned int IapObj::GetSecNum (void *adr)
{
unsigned int n;
n = ((unsigned int)adr >> 12) & 0x7F; // Pseudo Sector Number
if (n >= 0x78) { // High Small 4kB Sectors
n -= 0x62;
}
else if (n >= 0x08) { // Large 32kB Sectors
n = 0x07 + (n >> 3);
}
return (n); // Sector Number
}
bool IapObj::SelSector(void* start, void* end)
{
bool result;
IAPDR.cmd = IAP_SELECTOR;//选择扇区
IAPDR.par[0] = GetSecNum(start);//开始扇区
IAPDR.par[1] = GetSecNum(end); //结束扇区
IapExec();// 调用IAP服务程序
result = (IAPDR.stat == CMD_SUCCESS);
return result;
}
bool IapObj::EraseSector(void* start, void* end)
{
bool result;
result = SelSector(start, end);
if (result) {
IAPDR.cmd = IAP_ERASESECTOR;//擦除扇区
IAPDR.par[2] = IAP_FCCLK;
IapExec();// 调用IAP服务程序
result = (IAPDR.stat == CMD_SUCCESS);
}
return result;
}
bool IapObj::ProgramPage(void * flash, void * ram, unsigned int size)
{
bool result = false;
size &= 0xfffffffc;//必须是32位4个字节
if (size) {
/*
IAPDR.cmd = IAP_SELECTOR;//选择扇区
IAPDR.par[0] = GetSecNum(flash);//目的扇区
IAPDR.par[1] = IAPDR.par[0];//GetSecNum((void *)((unsigned int)flash + (size - 1))); //源扇区
IapExec();// 调用IAP服务程序
result = (IAPDR.stat == CMD_SUCCESS);
*/
result = SelSector(flash, (void *)((int)flash + size - 1));
if (result) {
IAPDR.cmd = IAP_RAMTOFLASH;//拷贝数据
IAPDR.par[0] = (unsigned int)flash; //写入数据字节的目标Flash地址。目标地址的边界应当为256字节为边界。
IAPDR.par[1] = (unsigned int)ram;//读出数据字节的源RAM地址。该地址应当以字为边界。
IAPDR.par[2] = size;//写入字节的数目。应当为256/512/1024/4096.
IAPDR.par[3] = IAP_FCCLK;//系统时钟频率(CCLK)(单位:KHz)
IapExec();//调用IAP服务程序
result = (IAPDR.stat == CMD_SUCCESS);
}
}
return result;
}
/*----------------------------------------------------------------------------
* Main: Initialize and start ARTX Kernel
*---------------------------------------------------------------------------*/
int main (void) { /* program execution starts here */
Enable_IRQ();//开中断
os_sys_init (MainTask);//启动ARTX,此函数并不返回main()
}
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -