mini2440 IIC 裸机程序记录

调了两天终于把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<times; 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, 0\n"
		"orr	r1, r1, #0xc0000000\n"
		"mcr	p15, 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 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] != '\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 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!\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 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
	IICSTAT = 0xd0;
	IICCON = 0b00101111; //recover the transmission
	delay(3);

	return read_data;
}

//write 8 bytes to eeprom
void 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 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);

	for(i=0; i<8; i++)
	{
		//send data
		write_ack = 0;
		IICDS = pdata[i];
		IICCON = 0b00101111; //recover the transmission
		while(!write_ack);
	}

	//send P signal
	IICSTAT = 0xd0;
	IICCON = 0b00101111; //recover the transmission
	delay(3);
}

//read bytes continuioiusly
void 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 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
	*/
	for(i=0; i<length; i++)
	{
		iic_mode = 0; //read mode
		read_over = 0;
		if(i<length-1)
			IICCON = 0b10101111; //recover the transmission with ack
		else
			IICCON = 0b00101111; //recover the transmission without ack

		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
		*/
		buffer[i] = IICDS;
		while(!read_over);
	}

	//send P signal
	IICSTAT = 0xd0;
	IICCON = 0b00101111; //recover the transmission
	delay(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页数据和读取数据的截图,下面是串口最后的输出结果:

要在Qt上实现mini2440IIC,你需要进行以下步骤: 1. 安装Qt的开发环境和交叉编译工具链,以便能够将程序编译成可在mini2440上运行的二进制文件。 2. 在Qt中创建一个新的项目,并将其配置为使用交叉编译工具链。 3. 编写代码来初始化mini2440IIC控制器,并设置从机地址、传输速率等参数。 4. 在代码中使用Qt的串口通信库来进行IIC数据传输,并将读取到的数据显示在Qt的界面上。 下面是一个简单的示例程序,演示如何在Qt中实现mini2440IIC: ```cpp #include <QCoreApplication> #include <QSerialPort> #include <QDebug> #define IIC_BUS "/dev/i2c-0" #define IIC_ADDRESS 0x50 int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // 初始化串口 QSerialPort serialPort; serialPort.setPortName(IIC_BUS); serialPort.setBaudRate(QSerialPort::Baud115200); serialPort.setDataBits(QSerialPort::Data8); serialPort.setParity(QSerialPort::NoParity); serialPort.setStopBits(QSerialPort::OneStop); serialPort.setFlowControl(QSerialPort::NoFlowControl); // 打开串口 if (!serialPort.open(QIODevice::ReadWrite)) { qDebug() << "Failed to open serial port"; return 1; } // 初始化IIC控制器 char initCmd[] = {0x00, 0x01, 0x02, 0x03}; if (serialPort.write(initCmd, sizeof(initCmd)) < 0) { qDebug() << "Failed to initialize IIC controller"; return 1; } // 设置从机地址 char setAddrCmd[] = {0x10, IIC_ADDRESS}; if (serialPort.write(setAddrCmd, sizeof(setAddrCmd)) < 0) { qDebug() << "Failed to set IIC address"; return 1; } // 读取数据 char readCmd[] = {0x20, 0x00, 0x00}; if (serialPort.write(readCmd, sizeof(readCmd)) < 0) { qDebug() << "Failed to send read command"; return 1; } char buffer[256]; if (serialPort.read(buffer, sizeof(buffer)) < 0) { qDebug() << "Failed to read data"; return 1; } // 显示读取到的数据 qDebug() << "Read data:" << buffer; // 关闭串口 serialPort.close(); return a.exec(); } ``` 注意,这只是一个简单的示例程序,并且假设你已经正确地配置了Qt的交叉编译环境和mini2440的硬件环境。在实际使用中,你需要根据实际情况进行更多的调试和修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值