mini2440 IIC 裸机程序记录

来源:互联网 发布:ios定时关机软件 编辑:程序博客网 时间:2024/04/29 21:19

调了两天终于把2440上面的IIC调通了,代码记录如下:

head.s

 

@this is a test program of uart using com0, the properties of com0 is the same as usual (115200,8, 1, n, n).text.global _start_start:bResetb. @undefined instructionb. @swib. @pregetch instructionb. @data abortb. @ReservedbHandleIRQ @irqb. @fiqReset:ldrsp, =4096 @set the stack pointer of sys mode to 4096bldisable_watchdogblinit_ledblinit_sdramblcopy_sdramldrpc, =on_sdramon_sdram:msrcpsr_c, #0xd2 @set cpu to irq modeldrsp, =3072 @set the stack pointer of irq mode to 3072msrcpsr_c, #0xdf @reset cpu to sys modeblinit_clockmovr0, #1movr1, #10blblinkblinit_iicmovr0, #2movr1, #10blblinkblinit_com0movr0, #3movr1, #10blblinkblinit_irqmsrcpsr_c, #0x5f @enable irqbl mainb..ltorg.ltorg.ltorgHandleIRQ:sublr, lr, #4stmdbsp!, {r0-r12, lr}ldrlr, =nextldrpc, =interrupt_funcnext:ldmiasp!, {r0-r12, pc}^ @return to main.ltorg.ltorg


init.c

#defineGPBCON(*((volatile unsigned long*)(0x56000010)))#defineGPBDAT(*((volatile unsigned long*)(0x56000014)))#defineWTCON       (*((volatile unsigned long*)(0x53000000)))#defineLOCKTIME(*((volatile unsigned long*)(0x4C000000)))#defineCLKDIVN(*((volatile unsigned long*)(0x4C000014)))#defineMPLLCON(*((volatile unsigned long*)(0x4C000004)))#defineTCFG0(*((volatile unsigned long*)(0x51000000)))#defineTCFG1(*((volatile unsigned long*)(0x51000004)))#defineTCNTB0(*((volatile unsigned long*)(0x5100000C)))#defineTCON(*((volatile unsigned long*)(0x51000008)))#defineINTMSK(*((volatile unsigned long*)(0X4A000008)))#defineINTSUBMASK(*((volatile unsigned long*)(0X4A00001C)))#defineGPHCON(*((volatile unsigned long*)(0x56000070)))#defineGPHUP(*((volatile unsigned long*)(0x56000078)))//control register of com0#defineULCON0(*((volatile unsigned long*)(0x50000000)))#defineUCON0(*((volatile unsigned long*)(0x50000004)))#defineUFCON0(*((volatile unsigned long*)(0x50000008)))#defineUMCON0(*((volatile unsigned long*)(0x5000000C)))#defineUBRDIV0(*((volatile unsigned long*)(0x50000028)))//the control register of sckl, sdat (IIC)#defineGPECON(*((volatile unsigned long*)(0x56000040)))#defineGPEUP(*((volatile unsigned long*)(0x56000048)))#defineIICCON(*((volatile unsigned long*)(0x54000000)))#defineIICSTAT(*((volatile unsigned long*)(0x54000004)))//initilize GPB to output modevoid init_led(){GPBCON  &= (~(0xff<<10));GPBCON  |= (0X55<<10);}void delay(int times){int i, j;for(i=0; i<times; i++){for(j=0; j<1000; j++);}}//blink function is used to debugvoid blink(int number, int delay_num){GPBDAT|= (0X0F<<5);GPBDAT&= (~(number<<5));delay(delay_num);GPBDAT|= (0X0F<<5);delay(delay_num);}void disable_watchdog(){WTCON = 0;}void init_clock(){LOCKTIME = 0xffffffff;CLKDIVN = 0X03; //fclk:hclk:pclk=1:2:4__asm__("mrcp15, 0, r1, c1, c0, 0\n""orrr1, r1, #0xc0000000\n""mcrp15, 0, r1, c1, c0, 0\n");MPLLCON = (92<<12)|(1<<4)|(2<<0); //fclk=200M, hclk=100M, pclk=50M }void init_sdram(){volatile unsigned long *p = (volatile unsigned long *)(0x48000000);    p[0] = 0x22011110;     //BWSCON    p[1] = 0x00000700;     //BANKCON0    p[2] = 0x00000700;     //BANKCON1    p[3] = 0x00000700;     //BANKCON2    p[4] = 0x00000700;     //BANKCON3      p[5] = 0x00000700;     //BANKCON4    p[6] = 0x00000700;     //BANKCON5    p[7] = 0x00018005;     //BANKCON6    p[8] = 0x00018005;     //BANKCON7    p[9] = 0x008C04F4;   //REFRESH value is different than before, because the clock is different    p[10] = 0x000000B1;     //BANKSIZE    p[11] = 0x00000030;     //MRSRB6    p[12] = 0x00000030;     //MRSRB7}void copy_sdram(){unsigned long* src = (unsigned long *)(0);unsigned long* des = (unsigned long *)(0x30000000);int i;for(i=0; i<1024; i++){des[i] = src[i];}}void init_irq(){//enable interrupt of rxd0 txd0INTSUBMASK &= (~(0b11));//enable interrupt of uart0INTMSK &= (~(1<<28));//enable IIC interruptINTMSK &= (~(1<<27));}//initialize the IIC busvoid init_iic(){//set gpe[14:15] used for IICGPECON &= (~(0b1111<<28));GPECON |= (0b1010<<28);//enable the pulling up functionGPEUP &= (~(0b11<<14));/*0b00100111[7] disable ack signal[6] IICCLK=PCLK/16[5] enable IIC rx interrupt and tx interrupt[4] clear IIC interrupt[3:0] tx clock = IICCLK/8 = 50000000/16/16 = 195.3125KHz*/IICCON = 0b00101111;//enable IIC R/T abilityIICSTAT = 0x10;}void init_com0(){//set gph[2:3] used as txd and rxd for com0GPHCON &= (~(0xff<<4));GPHCON |= (0x0a<<4);//disable pull up functon for gph[2:3]GPHUP = 0x0c;//set properties of com0ULCON0 = 0b00000011;//enable the rxd and txd, and interrupt will happen when con0 received data or the send buffer is empty in non-fifo modeUCON0 = 0b00000101;//disable fifoUFCON0 = 0x00;//disable fifoUMCON0 = 0x00;//set baud-rate to 115200UBRDIV0 = (int)(50000000/(115200*16)) -1;}


 

com0.c

#defineUTRSTAT0(*((volatile unsigned long*)(0x50000010)))#defineUTXH0(*((volatile unsigned long*)(0x50000020)))#defineURXH0(*((volatile unsigned long*)(0x50000024)))#defineSUBSRCPND(*((volatile unsigned long*)(0X4A000018)))#defineSRCPND(*((volatile unsigned long*)(0X4A000000)))#defineINTPND(*((volatile unsigned long*)(0X4A000010)))#defineIICSTAT(*((volatile unsigned long*)(0x54000004)))#defineIICDS(*((volatile unsigned long*)(0x5400000C)))extern void blink(int, int);extern unsigned char write_ack;extern unsigned char iic_mode;extern unsigned char read_over;extern unsigned char read_data;void put_char(char ch){while (!(UTRSTAT0 & (1<<2)));UTXH0 = ch;}unsigned char get_char(){while (!(UTRSTAT0 & (1<<0)));return URXH0;}void put_string(char *string){int i = 0;while(string[i] != '\0')put_char(string[i++]);}void com0_read(char *ch){*ch = URXH0;}void com0_write(char ch){UTXH0 = ch;}//the function to serve the uart0 interruptvoid interrupt_func(){//uart0 interruptif(INTPND & (1<<28)){char ch;//rxd sub interruptif(SUBSRCPND & (1<<0)){com0_read(&ch);if(ch == '\r'){com0_write('\r');com0_write('\n');}else{com0_write(ch);}}else if(SUBSRCPND & (1<<1)) //txd interrupt{}//clear the interrupt of uart0SUBSRCPND = SUBSRCPND;SRCPND |= (1<<28);INTPND = INTPND;}else if(INTPND & (1<<27)) //IIC interrupt{put_string("IIC interrupt!\r\n");if(iic_mode) //write mode{if(!(IICSTAT&(1<<0))){write_ack = 1;put_string("get ack!\r\n");}else{write_ack = 0;put_string("no ack!\r\n");}}else //read mode{read_over = 1;put_string("get data\r\n");}//clear the interruptSRCPND |= (1<<27);INTPND = INTPND;}}


 

IIC.c

#defineIICDS(*((volatile unsigned long*)(0x5400000C)))#defineIICSTAT(*((volatile unsigned long*)(0x54000004)))#defineIICCON(*((volatile unsigned long*)(0x54000000)))extern void delay(int);extern void put_string(char *);//the ack signal form slave deviceunsigned char write_ack = 0;//the data read from IIC slave deviceunsigned char read_data = 0;//the mode of iic, 0----read mode , 1----write modeunsigned char iic_mode = 0;//the flag of whether reading is overunsigned char read_over = 0;/*write one byte to slave devicesalve_addr ---- the address of slave addressdata_addr ---- the address of the byte writen by hostdata ----- the writen data*/void iic_write(unsigned char slave_addr, int data_addr, unsigned char data){slave_addr &= 0b11111110;iic_mode = 1; //write mode//send S signal and the slave addresswrite_ack = 0;IICDS = slave_addr;IICSTAT = 0xf0;//wait the interrupt to change write_ackwhile(!write_ack);//send data_addrwrite_ack = 0;IICDS = data_addr;IICCON = 0b00101111; //recover the transmissionwhile(!write_ack);//send datawrite_ack = 0;IICDS = data;IICCON = 0b00101111; //recover the transmissionwhile(!write_ack);//send P signalIICSTAT = 0xd0;IICCON = 0b00101111; //recover the transmissiondelay(3);}//read a byte from slave deviceunsigned char iic_read(unsigned char slave_addr, int data_addr){slave_addr &= 0b11111110;iic_mode = 1; //write mode//send S signal and the slave addresswrite_ack = 0;IICDS = slave_addr;IICSTAT = 0xf0;//wait the interrupt to change write_ackwhile(!write_ack);//send data_addrwrite_ack = 0;IICDS = data_addr;IICCON = 0b00101111; //recover the transmissionwhile(!write_ack);//send S signal and the slave addressslave_addr |= 0b00000001;write_ack = 0;IICDS = slave_addr;IICSTAT = 0b10110000;IICCON = 0b00101111; //recover the transmission//wait the interrupt to change write_ackwhile(!write_ack);/*here is the most important partwe must clear IICCON[4] to inter IIC read interrupt*/iic_mode = 0; //read moderead_over = 0;IICCON = 0b00101111; //recover the transmissiondelay(5);/*we only need to read once, but two interrupt will happenthe first interrupt happens because of receiving data from slave devicethe second interrupt happens because of getting data from IICDS*/read_data = IICDS;while(!read_over)//send P signalIICSTAT = 0xd0;IICCON = 0b00101111; //recover the transmissiondelay(3);return read_data;}//write 8 bytes to eepromvoid iic_write_page(unsigned char slave_addr, int data_addr, unsigned char *pdata){int i;slave_addr &= 0b11111110;iic_mode = 1; //write mode//send S signal and the slave addresswrite_ack = 0;IICDS = slave_addr;IICSTAT = 0xf0;//wait the interrupt to change write_ackwhile(!write_ack);//send data_addrwrite_ack = 0;IICDS = data_addr;IICCON = 0b00101111; //recover the transmissionwhile(!write_ack);for(i=0; i<8; i++){//send datawrite_ack = 0;IICDS = pdata[i];IICCON = 0b00101111; //recover the transmissionwhile(!write_ack);}//send P signalIICSTAT = 0xd0;IICCON = 0b00101111; //recover the transmissiondelay(3);}//read bytes continuioiuslyvoid iic_serial_read(unsigned char slave_addr, int data_addr, unsigned char *buffer, int length){int i;slave_addr &= 0b11111110;iic_mode = 1; //write mode//send S signal and the slave addresswrite_ack = 0;IICDS = slave_addr;IICSTAT = 0xf0;//wait the interrupt to change write_ackwhile(!write_ack);//send data_addrwrite_ack = 0;IICDS = data_addr;IICCON = 0b00101111; //recover the transmissionwhile(!write_ack);//send S signal and the slave addressslave_addr |= 0b00000001;write_ack = 0;IICDS = slave_addr;IICSTAT = 0b10110000;IICCON = 0b00101111; //recover the transmission//wait the interrupt to change write_ackwhile(!write_ack);/*here is the most important partwe must clear IICCON[4] to inter IIC read interrupt*/for(i=0; i<length; i++){iic_mode = 0; //read moderead_over = 0;if(i<length-1)IICCON = 0b10101111; //recover the transmission with ackelseIICCON = 0b00101111; //recover the transmission without ackdelay(5);/*we only need to read once, but two interrupt will happenthe first interrupt happens because of receiving data from slave devicethe second interrupt happens because of getting data from IICDS*/buffer[i] = IICDS;while(!read_over);}//send P signalIICSTAT = 0xd0;IICCON = 0b00101111; //recover the transmissiondelay(3);}

 

main.c

extern void put_char(char);extern unsigned char get_char();extern void put_string(char *);extern void blink(int, int);extern void put_string(char*);extern void delay(int);extern void iic_write(unsigned char,int,unsigned char);extern unsigned char iic_read(unsigned char, int);extern void iic_write_page(unsigned char,int,unsigned char*);extern void iic_serial_read(unsigned char, int, unsigned char*, int);int main(void){unsigned char i;unsigned char ch = 48;unsigned char ch_array[8];unsigned char read_buffer[8];for(i=0; i<8; i++){ch_array[i] = 'a'+i;}put_string("\r\nthis is a test of IIC\r\n");//iic_write(0b10100000, 0, 65);//iic_write(0b10100000, 1024, 66);iic_write_page(0b10100000, 0, ch_array);iic_serial_read(0b10100000, 0, read_buffer, 8);//ch = iic_read(0b10100000, 7);for(i=0; i<8; i++){put_char(read_buffer[i]);}//put_string("get char:\r\n");//put_char(ch);while(1);return 0;}


 


最后粘上IIC写1页数据和读取数据的截图,下面是串口最后的输出结果:

原创粉丝点击