历史上的今天
返回首页

历史上的今天

今天是:2025年10月13日(星期一)

正在发生

2022年10月13日 | mini2440 IIC 裸机程序记录

2022-10-13 来源:csdn

调了两天终于把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:

b Reset

b . @undefined instruction

b . @swi

b . @pregetch instruction

b . @data abort

b . @Reserved

b HandleIRQ @irq

b . @fiq

Reset:

ldr sp, =4096 @set the stack pointer of sys mode to 4096

bl disable_watchdog

bl init_led

bl init_sdram

bl copy_sdram

ldr pc, =on_sdram

on_sdram:

msr cpsr_c, #0xd2 @set cpu to irq mode

ldr sp, =3072 @set the stack pointer of irq mode to 3072

msr cpsr_c, #0xdf @reset cpu to sys mode

bl init_clock

mov r0, #1

mov r1, #10

bl blink

bl init_iic

mov r0, #2

mov r1, #10

bl blink

bl init_com0

mov r0, #3

mov r1, #10

bl blink

bl init_irq

msr cpsr_c, #0x5f @enable irq

bl main

b .

.ltorg

.ltorg

.ltorg

HandleIRQ:

sub lr, lr, #4

stmdb sp!, {r0-r12, lr}

ldr lr, =next

ldr pc, =interrupt_func

next:

ldmia sp!, {r0-r12, pc}^ @return to main

.ltorg

.ltorg



init.c


#define GPBCON (*((volatile unsigned long*)(0x56000010)))

#define GPBDAT (*((volatile unsigned long*)(0x56000014)))

#define WTCON       (*((volatile unsigned long*)(0x53000000)))

#define LOCKTIME (*((volatile unsigned long*)(0x4C000000)))

#define CLKDIVN (*((volatile unsigned long*)(0x4C000014)))

#define MPLLCON (*((volatile unsigned long*)(0x4C000004)))

#define TCFG0 (*((volatile unsigned long*)(0x51000000)))

#define TCFG1 (*((volatile unsigned long*)(0x51000004)))

#define TCNTB0 (*((volatile unsigned long*)(0x5100000C)))

#define TCON (*((volatile unsigned long*)(0x51000008)))

#define INTMSK (*((volatile unsigned long*)(0X4A000008)))

#define INTSUBMASK (*((volatile unsigned long*)(0X4A00001C)))

 

#define GPHCON (*((volatile unsigned long*)(0x56000070)))

#define GPHUP (*((volatile unsigned long*)(0x56000078)))

//control register of com0

#define ULCON0 (*((volatile unsigned long*)(0x50000000)))

#define UCON0 (*((volatile unsigned long*)(0x50000004)))

#define UFCON0 (*((volatile unsigned long*)(0x50000008)))

#define UMCON0 (*((volatile unsigned long*)(0x5000000C)))

#define UBRDIV0 (*((volatile unsigned long*)(0x50000028)))

 

//the control register of sckl, sdat (IIC)

#define GPECON (*((volatile unsigned long*)(0x56000040)))

#define GPEUP (*((volatile unsigned long*)(0x56000048)))

#define IICCON (*((volatile unsigned long*)(0x54000000)))

#define IICSTAT (*((volatile unsigned long*)(0x54000004)))

 

//initilize GPB to output mode

void init_led()

{

GPBCON  &= (~(0xff<<10));

GPBCON  |= (0X55<<10);

}

 

void delay(int times)

{

int i, j;

for(i=0; i {

for(j=0; j<1000; j++);

}

}

 

//blink function is used to debug

void 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__

(

"mrc p15, 0, r1, c1, c0, 0n"

"orr r1, r1, #0xc0000000n"

"mcr p15, 0, r1, c1, c0, 0n"

);

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 txd0

INTSUBMASK &= (~(0b11));

//enable interrupt of uart0

INTMSK &= (~(1<<28));

//enable IIC interrupt

INTMSK &= (~(1<<27));

}

 

//initialize the IIC bus

void init_iic()

{

//set gpe[14:15] used for IIC

GPECON &= (~(0b1111<<28));

GPECON |= (0b1010<<28);

 

//enable the pulling up function

GPEUP &= (~(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 ability

IICSTAT = 0x10;

}

 

void init_com0()

{

//set gph[2:3] used as txd and rxd for com0

GPHCON &= (~(0xff<<4));

GPHCON |= (0x0a<<4);

 

//disable pull up functon for gph[2:3]

GPHUP = 0x0c;

//set properties of com0

ULCON0 = 0b00000011;

//enable the rxd and txd, and interrupt will happen when con0 received data or the send buffer is empty in non-fifo mode

UCON0 = 0b00000101;

//disable fifo

UFCON0 = 0x00;

//disable fifo

UMCON0 = 0x00;

//set baud-rate to 115200

UBRDIV0 = (int)(50000000/(115200*16)) -1;

}



 


com0.c


#define UTRSTAT0 (*((volatile unsigned long*)(0x50000010)))

#define UTXH0 (*((volatile unsigned long*)(0x50000020)))

#define URXH0 (*((volatile unsigned long*)(0x50000024)))

 

#define SUBSRCPND (*((volatile unsigned long*)(0X4A000018)))

#define SRCPND (*((volatile unsigned long*)(0X4A000000)))

#define INTPND (*((volatile unsigned long*)(0X4A000010)))

 

#define IICSTAT (*((volatile unsigned long*)(0x54000004)))

#define IICDS (*((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] != '')

put_char(string[i++]);

}

 

void com0_read(char *ch)

{

*ch = URXH0;

}

 

void com0_write(char ch)

{

UTXH0 = ch;

}

 

//the function to serve the uart0 interrupt

void interrupt_func()

{

//uart0 interrupt

if(INTPND & (1<<28))

{

char ch;

//rxd sub interrupt

if(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 uart0

SUBSRCPND = SUBSRCPND;

SRCPND |= (1<<28);

INTPND = INTPND;

}

else if(INTPND & (1<<27)) //IIC interrupt

{

put_string("IIC interrupt!rn");

if(iic_mode) //write mode

{

if(!(IICSTAT&(1<<0)))

{

write_ack = 1;

put_string("get ack!rn");

}

else

{

write_ack = 0;

put_string("no ack!rn");

}

}

else //read mode

{

read_over = 1;

put_string("get datarn");

}

 

//clear the interrupt

SRCPND |= (1<<27);

INTPND = INTPND;

}

 

}

 



 


IIC.c


#define IICDS (*((volatile unsigned long*)(0x5400000C)))

#define IICSTAT (*((volatile unsigned long*)(0x54000004)))

#define IICCON (*((volatile unsigned long*)(0x54000000)))

 

extern void delay(int);

extern void put_string(char *);

 

//the ack signal form slave device

unsigned char write_ack = 0;

//the data read from IIC slave device

unsigned char read_data = 0;

//the mode of iic, 0----read mode , 1----write mode

unsigned char iic_mode = 0;

//the flag of whether reading is over

unsigned char read_over = 0;

 

/*

write one byte to slave device

salve_addr ---- the address of slave address

data_addr ---- the address of the byte writen by host

data ----- 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 address

write_ack = 0;

IICDS = slave_addr;

IICSTAT = 0xf0;

//wait the interrupt to change write_ack

while(!write_ack);

 

//send data_addr

write_ack = 0;

IICDS = data_addr;

IICCON = 0b00101111; //recover the transmission

while(!write_ack);

 

//send data

write_ack = 0;

IICDS = data;

IICCON = 0b00101111; //recover the transmission

while(!write_ack);

 

//send P signal

IICSTAT = 0xd0;

IICCON = 0b00101111; //recover the transmission

delay(3);

}

 

//read a byte from slave device

unsigned char iic_read(unsigned char slave_addr, int data_addr)

{

slave_addr &= 0b11111110;

iic_mode = 1; //write mode

//send S signal and the slave address

write_ack = 0;

IICDS = slave_addr;

IICSTAT = 0xf0;

//wait the interrupt to change write_ack

while(!write_ack);

 

//send data_addr

write_ack = 0;

IICDS = data_addr;

IICCON = 0b00101111; //recover the transmission

while(!write_ack);

 

//send S signal and the slave address

slave_addr |= 0b00000001;

write_ack = 0;

IICDS = slave_addr;

IICSTAT = 0b10110000;

IICCON = 0b00101111; //recover the transmission

//wait the interrupt to change write_ack

while(!write_ack);

 

/*

here is the most important part

we must clear IICCON[4] to inter IIC read interrupt

*/

iic_mode = 0; //read mode

read_over = 0;

IICCON = 0b00101111; //recover the transmission

delay(5);

/*

we only need to read once, but two interrupt will happen

the first interrupt happens because of receiving data from slave device

the second interrupt happens because of getting data from IICDS

*/

read_data = IICDS;

while(!read_over)

//send P signal

推荐阅读

史海拾趣

DELTA公司的发展小趣事

Delta公司自1971年成立以来,始终专注于电源管理领域。最初,公司主要生产开关式电源供应器,但随着技术的不断进步和市场的不断扩大,Delta逐渐将产品线扩展到散热管理解决方案、零组件等多个领域。凭借其高效、可靠的产品,Delta在全球电源管理市场上树立了良好的口碑,并逐步成为该领域的领军企业。

CHIMEI(奇美)公司的发展小趣事

奇美公司自成立以来,始终坚持品质至上的原则。公司注重产品质量和性能的提升,通过引进先进的生产设备和工艺技术,不断提升产品的品质和竞争力。同时,奇美还建立了完善的质量管理体系,从原材料采购到产品出厂,每一个环节都严格把控,确保产品的品质达到客户的要求。这种对品质的执着追求,使得奇美的产品在市场上赢得了良好的口碑。

Clover Display Limited公司的发展小趣事

Clover Display Limited的创始团队最初是Kontoy Products Company Limited的成员,专注于电子板组装。随着技术的不断进步和市场需求的转变,团队意识到液晶显示技术的巨大潜力。于是,在1983年,他们决定成立一家专注于显示器研发与销售的新公司——Clover Display Limited。初期,公司面临着资金短缺、技术壁垒等多重挑战,但凭借着对技术的热情和市场的敏锐洞察力,他们逐步攻克难关,开始在液晶显示领域崭露头角。

Dynex公司的发展小趣事

随着中国内销市场的不断扩大,Clover Display Limited看到了巨大的商机。为了更好地服务中国内销客户,公司在2001年在深圳南山区成立了高华电子显示(深圳)有限公司。这家子公司以独资经营方式运作,可以开具增值税发票,以人民币结算,从而更加便捷地服务中国客户。深圳子公司的成立不仅拓宽了公司的销售渠道,也为其在中国市场的进一步发展奠定了坚实基础。

DAYLIGHT公司的发展小趣事

随着全球环保意识的提高,DAYLIGHT公司也开始注重环保和可持续发展。公司投入大量资金用于研发环保型电子产品和技术,并积极参与环保公益活动。此外,DAYLIGHT还制定了严格的环保标准和生产流程,确保其产品的生产和使用过程中对环境的影响最小化。

ENERGIZER公司的发展小趣事

ENERGIZER在电池技术的研发上一直处于行业领先地位。1957年,公司成功研制出首粒碱性电池,这一创新性的产品迅速占领了市场,成为了当时最受欢迎的电池产品之一。随后,ENERGIZER又相继推出了纽扣电池、测电带电池等一系列创新产品,不断满足消费者对电池的多样化需求。这些创新性的产品的研发和推广,进一步巩固了ENERGIZER在全球电池市场的领先地位。

问答坊 | AI 解惑

我也来秀一下我们的LPC11XX的板子

  本来拍的很清楚的,怎么到了这里就不清楚了。 …

查看全部问答>

计算机软硬件的发展趋势及应用

计算机软硬件的发展趋势及应用…

查看全部问答>

在WINXP下用cygwin编译ACE5.5 for vxworks5.5 出错,谁能帮帮我

我的环境 winxp(sp2), tornador2.2.1 cygwin perl ace5.5 我在编译时出现如下错误 Thread_Manager.cpp:In method \'int ACE_Thread_Manager::kill_grp(int, int)\': Thread_Manager.cpp:1636: Internal compiler error in \'verify_local ...…

查看全部问答>

应急灯原理图重新修改提交

由于以前选用电池管理芯片,MAX1924V, 美信半导体不提供免费的芯片。所以修改设计,重新选用MAX17005B做为电池管理芯片,修改原理图,并已经到美信网站申请了芯片MAX17005B和MAX8790A LED驱动芯片。最新原理图如下: …

查看全部问答>

初学430 求教

想知道现在430的活力能持续多久呢?…

查看全部问答>

使用IAR软件仿真STM32程序,如何知道每条指令运行的时间呢?

                                 在哪个选项里面可以得到答案?我使用的是IAR for ARM 4.42版本的。…

查看全部问答>

求帮忙,各位神侠,帮帮小女子吧

我们要求设计基于单片机的交流参数测试仪,我虽然有一点思路,但是还是很模糊,求求各位帮忙讲解下原理,采集、参数好像有电压、电流、功率…

查看全部问答>

武林学习LM3S811(六)触摸芯片XPT2046驱动

触摸控制器芯片介绍: XPT2046内部有 2.5V的参考电压源,可以作为辅助输入、电池电压测量和片内温度测量的参考电压。当不使用时,参考电压源可以处于省电模式。内部参考电压源在电源电压低至2.7V时仍可正常工作。当不使用时,参考电压还可以处于省 ...…

查看全部问答>

请大家推荐一块BeagleBone用4寸800*480左右分辨率的TFT屏

正在画BeagleBone的扩展板,BeagleBone自带了LCD控制器,输出电平信号,请大家推荐一块4寸800*480左右分辨率的TFT屏,最好是不需要电平转换直接就能用的,一经采用可以赠送一块扩展板或者其他的开发板,谢谢!…

查看全部问答>

请教大虾关于msp430f5438的问题,非常急

各位大虾好 之前我用msp430f149的SPI控制nrf24l01 做到了正常通信 最近使用msp430f5438将程序移植 却始终无法通信 。在示波器上看时序 发现5438的SPI中的MOSI CLK都正常工作。但是MISO读回的值始终为0XFF,程序改了好几次,一直不成功,我是第一次 ...…

查看全部问答>