显示标签为“SPI”的博文。显示所有博文
显示标签为“SPI”的博文。显示所有博文

星期日, 十二月 30, 2007

我写的spi按键的驱动程序

由于工作需要,学着写了工作以来第一个真正能用的基于spi通信的按键程序,至于为什么,优缺点之类的就不是我要考虑的了,因为硬件工程师已经给设计成这样了,所以我只管写就好了

下面是arm主程序:
主要是参考了网上大家的一些方法,至于很多东西自己也不是很清楚,毕竟做linux驱动才几个月,还有就是在选择按键码的部分,后来对应得键码换了好多次,所以注释和代码不一致,这部分是为了对应单片机所以一改再改,反正最后能用最重要,键码的修改也比较简单,放在这就当个备份吧,呵呵

/********************************************************************/
/********************************************************************/
/*********Description: SPI keyboard driver ***************/
/*********Author: Kenshinxf <xuefengwang101@gmail.com> ***************/
/*********Date: 2007/11/12 **************/
/********************************************************************/
/********************************************************************/

#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <linux/irq.h>
#include <linux/input.h>

#include <asm/irq.h>
#include <asm/io.h>

#include <asm/hardware.h>

#include <linux/module.h>
#include <linux/config.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/iobuf.h>
#include <linux/highmem.h>
#include <linux/in.h>
#include <linux/vmalloc.h>
#include <asm/io.h>
#include <linux/errno.h>
#include <linux/tqueue.h>
#include <linux/wait.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/keyboard.h>

#ifdef CONFIG_DEVFS_FS
#include <linux/devfs_fs_kernel.h>
#endif
#include <linux/kbd_kern.h>

devfs_handle_t MegaKbd_devfs_dir;
//#define spi_debug

void input_register_device (struct input_dev *);

void input_unregister_device (struct input_dev *);

void input_register_handler (struct input_handler *);
void input_unregister_handler (struct input_handler *);

int input_open_device (struct input_handle *);
void input_close_device (struct input_handle *);

devfs_handle_t input_register_minor (char *name, int minor, int minor_base);
void input_unregister_minor (devfs_handle_t handle);

void input_event (struct input_dev *dev, unsigned int type, unsigned int code,
int value);

#define input_report_key(a,b,c) input_event(a, EV_KEY, b, !!(c))

#define DEVICE_NAME "MegaKbd"
#define MegaKbd_MAJOR 232

#define U8 unsigned char
#define U32 unsigned int

#define rSPCON0 (*(volatile unsigned long *)r_SPCON0) /*SPI control Register */
#define rSPSTA0 (*(volatile unsigned long *)r_SPSTA0) /*SPI status Register */
#define rSPPIN0 (*(volatile unsigned long *)r_SPPIN0) /* SPI pin control Register */
#define rSPPRE0 (*(volatile unsigned long *)r_SPPRE0) /*SPI Baud Rate Prescaler Register */
#define rSPTDAT0 (*(volatile unsigned long *)r_SPTDAT0) /*SPI Tx Data Register */
#define rSPRDAT0 (*(volatile unsigned long *)r_SPRDAT0) /*SPI Rx Data Register */

#define rGPECON (*(volatile unsigned long *)r_GPECON) /*Configure the pins of port E */
#define rGPEUP (*(volatile unsigned long *)r_GPEUP) /*Pull-up disable register for port E */
#define rGPGCON (*(volatile unsigned long *)r_GPGCON) /*Configure the pins of port G */
#define rGPGUP (*(volatile unsigned long *)r_GPGUP) /*Pull-up disable register for port G */
#define rGPGDAT (*(volatile unsigned long *)r_GPGDAT) /*The data register for port G */
unsigned long r_SPCON0, r_SPSTA0, r_SPPIN0, r_SPPRE0, r_SPTDAT0, r_SPRDAT0;
unsigned long r_GPECON, r_GPEUP;
unsigned long r_GPGCON, r_GPGUP, r_GPGDAT;

static struct input_dev *button_dev;

static void spi_poll_done (void);
void spi_tx_data (U8 data);

static int keycode = 0;
static DECLARE_WAIT_QUEUE_HEAD (key_wait);

/*address_map*/
int
address_map (void)
{
//SPI registers
r_SPCON0 = ioremap (0x59000000, 4);
r_SPSTA0 = ioremap (0x59000004, 4);
r_SPPIN0 = ioremap (0x59000008, 4);
r_SPPRE0 = ioremap (0x5900000C, 4);
r_SPTDAT0 = ioremap (0x59000010, 4);
r_SPRDAT0 = ioremap (0x59000014, 4);
//I/O registers
r_GPECON = ioremap (0x56000040, 4);
r_GPEUP = ioremap (0x56000048, 4);
r_GPGCON = ioremap (0x56000060, 4);
r_GPGUP = ioremap (0x56000068, 4);
r_GPGDAT = ioremap (0x56000064, 4);


return 0;
}

/**********************************************************/
static void spi_poll_done (void)
{
int j = 0;

while (!(rSPSTA0 & 0x01))
{
j++;
if (j >= 5000)
{
printk ("SPI state poll failed\n");
break;
}
} //endwhile
}

/**********************************************************/
void spi_tx_data (U8 data)
{
spi_poll_done ();
rSPTDAT0 = data; //transmit data
spi_poll_done ();
}

/**********************************************************/
void Init_SPI (void)
{
int i, config, value;
#ifdef spi_debug
printk ("************************\n*");
printk ("spi open program begin..\n");
printk ("now,GPE AND GPG port init...\n");
#endif

rSPPRE0 = 0xff;

#ifdef spi_debug
value = rSPPRE0;
printk ("rSPPRE0=0x%x\n", value);
#endif

for (i = 0; i < 10; i++)
{
rSPTDAT0 = 0xff;
}
rGPECON = (rGPECON & 0xf03fffff) | 0x0a800000; //GPECON-11,12,13=10
#ifdef spi_debug
value = rGPECON;
printk ("GPECON=0x%x\n", value);
#endif
rGPEUP |= 0x3800; //GPE11,12,13 pull-up disable

#ifdef spi_debug
value = rGPEUP;
printk ("GPEUP=0x%x\n", value);
#endif

rGPGCON = (rGPGCON & 0xffffffde) | 0x00000032;
#ifdef spi_debug
value = rGPGCON;
printk ("rGPGCON=0x%x\n", value);
#endif

rGPGUP |= 0x4; //GPG2 pull-up disable;
#ifdef spi_debug
value = rGPGUP;
printk ("rGPGUP=0x%x\n", value);
#endif

//select the chip
set_gpio_ctrl (GPIO_G2 | GPIO_PULLUP_EN | GPIO_MODE_OUT);
write_gpio_bit (GPIO_G2, 0);

#ifdef spi_debug
printk ("GPE AND GPG port init end!\n");
printk ("**************************\n");
#endif

}

/*********************Drive********************************/

static void megakbd_irq (int irq, void *dev_id, struct pt_regs *reg)
{
int i = 0;
int down = 0, keycode = 0;
int config;
char string;
#ifdef spi_debug
printk ("**************************\n");
printk ("\nThis is MegaKbd irq service\n");
printk ("SPI polling TX/RX Test...\n");
#endif
rSPCON0 = (1 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (0 << 1) | (0 << 0);
#ifdef spi_debug
config = (int) rSPCON0;
printk ("rSPCON0=0x%x\n", config);
#endif
//polling,en-sck,master,low,format A,nomal
rSPPIN0 = (0 << 2) | (1 << 1) | (0 << 0);
//Multi Master error detect disable,reserved,release
#ifdef spi_debug
config = (int) rSPPIN0;
printk ("rSPPIN0=0x%x\n", config);
#endif
spi_tx_data (0xff);
#ifdef spi_debug
string = rSPTDAT0;
printk ("transmit char=0x%x\n", string);
printk ("transmit char=%c\n", string);

string = rSPRDAT0;
printk ("receive char=%c\n", string);
printk ("receive char=0x%x\n", string);
#endif

keycode = rSPRDAT0;
#ifdef spi_debug
printk ("\nkeycode is %d\n", keycode);
#endif
switch (keycode)
{
case 255:
break;
/*
case 12: //1 down
keycode = KEY_1; //2;
down = 1;
break;
case 11: //1 up
keycode = KEY_1; //2;
break;
*/
case 42: //2 down
keycode = KEY_2; //3;
down = 1;
break;
case 41: //2 up
keycode = KEY_2; //3;
break;
/*
case 72: //3 down
keycode = KEY_3; //4;
down = 1;
break;
case 71: //3 up
keycode = KEY_3; //4;
break;
*/
//key #


case 9: //4 down
keycode = KEY_ENTER; //5;
down = 1;
break;
case 8: //4 up
keycode = KEY_ENTER; //5;
break;

case 39: //5 down
keycode = KEY_9; //6;
down = 1;
break;
case 38: //5 up
keycode = KEY_9; //6;
break;

case 69: //6 down
keycode = KEY_3; //7;
down = 1;
break;
case 68: //6 up
keycode = KEY_3; //7;
break;
case 6: //7 down
keycode = KEY_0; //8;
down = 1;
break;
case 5: //7 up
keycode = KEY_0; //8;
break;
case 36: //8 down
keycode = KEY_8; //9;
down = 1;
break;
case 35: //8 up
keycode = KEY_8; //9;
break;
case 66: //9 down
keycode = KEY_2; //10;
down = 1;
break;
case 65: //9 up
keycode = KEY_2; //10;
break;
case 33: //0 down
keycode = KEY_7; //11;
down = 1;
break;
case 32: //0 up
keycode = KEY_7; //11;
break;

//key *
case 3: //asterisk down shift+8
keycode = KEY_KPASTERISK; //55;
// keycode = KEY_LEFTSHIFT;
down = 1;
// input_report_key(&button_dev, keycode, down);
// input_sync(&button_dev);
// keycode = KEY_8;
// keycode = KEY_KPASTERISK; //55;
// down = 1;
break;
case 2: //asterisk up 8+shift
keycode = KEY_KPASTERISK; //55;
// keycode = KEY_8;
// input_report_key(&button_dev, keycode, down);
// input_sync(&button_dev);
// keycode = KEY_LEFTSHIFT;
// keycode = KEY_KPASTERISK; //55;
break;

case 63: //numbersign down shift+3
keycode = KEY_1;
// keycode = KEY_LEFTSHIFT;
down = 1;
// input_report_key(&button_dev, keycode, down);
// input_sync(&button_dev);
// keycode = KEY_3;
// keycode = KEY_KPPLUS;
// down = 1;
break;
case 62: //numbersign up 3+shift
keycode = KEY_1;
// input_report_key(&button_dev, keycode, down);
// input_sync(&button_dev);
// keycode = KEY_LEFTSHIFT;
// keycode = KEY_KPPLUS;
break;

case 27: //enter down
keycode = KEY_ENTER; //28;
down = 1;
break;
case 26: //enter up
keycode = KEY_ENTER; //28;
break;
case 57: //esc down
keycode = KEY_BACKSPACE; //1;
down = 1;
break;
case 56: //esc up
keycode = KEY_BACKSPACE; //1;
break;
case 15: //backspace down
keycode = KEY_S;
down = 1;
break;
case 14: //backspace up
keycode = KEY_S;
break;
case 75: //left down
keycode = KEY_LEFT;
down = 1;
break;
case 74: //left up
keycode = KEY_LEFT;
break;
case 60: //right down
keycode = KEY_L;
down = 1;
break;
case 59: //right up
keycode = KEY_L;
break;
case 30: //up down
keycode = KEY_UP;
down = 1;
break;
case 29: //up up
keycode = KEY_UP;
break;
/*
case 45: //down down
keycode = KEY_4;
down = 1;
break;
case 44: //down up
keycode = KEY_4;
break;
*/
case 24: //f1 down
keycode = KEY_F1;
down = 1;
break;
case 23: //f1 up
keycode = KEY_F1;
break;
case 54: //f2 down
keycode = KEY_6;
down = 1;
break;
case 53: //f2 up
keycode = KEY_6;
break;
case 21: //f3 down
keycode = KEY_F3;
down = 1;
break;
case 20: //f3 up
keycode = KEY_F3;
break;
case 51: //f4 down
keycode = KEY_5;
down = 1;
break;
case 50: //f4 up
keycode = KEY_5;
break;
case 18: //f5 down
keycode = KEY_F5;
down = 1;
break;
case 17: //f5 up
keycode = KEY_F5;
break;
case 48: //f6 down
keycode = KEY_4;
down = 1;
break;
case 47: //f6 up
keycode = KEY_4;
break;

default:;
}
#ifdef spi_debug
printk("keycode=0x%x\n",keycode);
#endif
if (keycode)
{
input_report_key (&button_dev, keycode, down);
// input_sync(&button_dev);
// printk("*********************[%d]", keycode);
}

// printk ("\nkeycode=[0x%x]\n", keycode);
// printk ("\nkeycode=[%d]\n", keycode);

handle_scancode (keycode, down);
tasklet_schedule (&keyboard_tasklet);
wake_up_interruptible (&key_wait);
}

//Read for megaKbd
static ssize_t megaKbd_read (struct file *file, char *buf, size_t count, loff_t * offset)
{
static int key;
key = keycode;
copy_to_user (buf, &key, sizeof key);
return sizeof keycode;

}


//Write to megaKbd
ssize_t megaKbd_write (struct file *file, char *buf, size_t count, loff_t * offset)
{

int i = 0;
int config;
int string;
#ifdef spi_debug
printk ("SPI polling TX/RX Test...\n");
printk ("Connet SPIMOSI0 into SPIMISO\n");
#endif
rSPCON0 = (1 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (0 << 1) | (0 << 0);
// config = (int) rSPCON0;
// printk ("rSPCON0=0x%x\n", config);

//polling,en-sck,master,low,format A,nomal
rSPPIN0 = (0 << 2) | (1 << 1) | (0 << 0);

//Multi Master error detect disable,reserved,release
// config = (int) rSPPIN0;
// printk ("rSPPIN0=0x%x\n", config);
spi_tx_data (*buf);
string = rSPTDAT0;
#ifdef spi_debug
printk ("\ntransmit char=%c\n", string);
printk ("transmit char=0x%x\n", string);
#endif
string = rSPRDAT0;
#ifdef spi_debug
printk (" receive char=%c\n\n\n", string);
printk (" receive char=0x%x\n\n\n", string);
printk ("****************\n");
printk ("****************\n");
printk ("****************\n");
printk ("****************\n");
printk ("****************\n");
printk ("****************\n");
#endif
return 0;

}

/**********************************************************/
//Open the megaKbd device
static int megaKbd_open (struct inode *inode, struct file *file)
{
return 0;
}

/**********************************************************/
//Close the megaKbd device
static int megaKbd_close (struct inode *inode, struct file *file)
{
return 0;
}

/**********************************************************/
static struct file_operations megaKbd_fops = {
owner:THIS_MODULE,
llseek:no_llseek,
read:megaKbd_read,
write:megaKbd_write,
open:megaKbd_open,
release:megaKbd_close,
};

static int __init HW_kbd_init (void)
{
unsigned int result;

// set_external_irq (IRQ_EINT8, EXT_FALLING_EDGE, GPIO_PULLUP_DIS);
set_external_irq (IRQ_EINT8, EXT_RISING_EDGE, GPIO_PULLUP_DIS);
disable_irq (IRQ_EINT8);
enable_irq (IRQ_EINT8);
result = request_irq (IRQ_EINT8, &megakbd_irq, SA_INTERRUPT, DEVICE_NAME, &megakbd_irq);
if (result)
{
printk ("Can't get assigned irq %d,result=%d\n", IRQ_EINT8, result);
return result;
}
}

static int mega_kbd_translate (U8 scancode, U8 * keycode, char raw_mode)
{
int Result = 1;
printk ("my transleate\n");
*keycode = (scancode & 0x7f);
return 1;
}


static int __init megaKbd_code (void)
{

/*
button_dev = input_allocate_device();
if (!button_dev) {
printk(KERN_ERR "input: not enough memory for input device\n");
return -ENOMEM;
}
*/
// input_register_device(&button_dev);
button_dev->name = "Spi Keyboard";
// button_dev->phys = "input/input0";
button_dev->evbit[0] = BIT (EV_KEY);
// button_dev->keybit[LONG(KEY_NUMLOCK)] = BIT(KEY_NUMLOCK);
set_bit (KEY_0, button_dev->keybit);
set_bit (KEY_1, button_dev->keybit);
set_bit (KEY_2, button_dev->keybit);
set_bit (KEY_3, button_dev->keybit);
set_bit (KEY_4, button_dev->keybit);
set_bit (KEY_5, button_dev->keybit);
set_bit (KEY_6, button_dev->keybit);
set_bit (KEY_7, button_dev->keybit);
set_bit (KEY_8, button_dev->keybit);
set_bit (KEY_9, button_dev->keybit);

set_bit (KEY_F1, button_dev->keybit);
set_bit (KEY_F2, button_dev->keybit);
set_bit (KEY_F3, button_dev->keybit);
set_bit (KEY_F4, button_dev->keybit);
set_bit (KEY_F5, button_dev->keybit);
set_bit (KEY_F6, button_dev->keybit);

set_bit (KEY_ENTER, button_dev->keybit);
set_bit (KEY_ESC, button_dev->keybit);
set_bit (KEY_UP, button_dev->keybit);
set_bit (KEY_DOWN, button_dev->keybit);
set_bit (KEY_LEFT, button_dev->keybit);
set_bit (KEY_RIGHT, button_dev->keybit);

set_bit (KEY_BACKSPACE, button_dev->keybit);
set_bit (KEY_LEFTSHIFT, button_dev->keybit);
set_bit (KEY_KPASTERISK, button_dev->keybit);
set_bit (KEY_KPPLUS, button_dev->keybit);

input_register_device (&button_dev);
return 0;
}


/**********************************************************/
// Install the megaKbd driver
static int __init megaKbd_init (void)
{
unsigned int result;

//Init Spi Device
address_map ();
Init_SPI ();

result = HW_kbd_init ();
if (result)
return result;

//k_translate = mega_kbd_translate;

megaKbd_code ();
result = register_chrdev (MegaKbd_MAJOR, DEVICE_NAME, &megaKbd_fops);
if (result < 0)
{
printk (DEVICE_NAME "cannot register maor number\n");
return result;
}

//Register device
MegaKbd_devfs_dir = devfs_mk_dir (NULL, "MegaKbd", NULL);

devfs_register (MegaKbd_devfs_dir, DEVICE_NAME, DEVFS_FL_AUTO_DEVNUM, 0, 0, S_IFCHR | S_IRUGO | S_IWUGO, &megaKbd_fops, NULL);
printk ("megaKbd driver installed OK\n");

return 0;
}

/**********************************************************/
// Remove the megaKbd driver
static void megaKbd_exit (void)
{
//Disable Interrupt
// disable_irq (IRQ_EINT8);
free_irq (IRQ_EINT8, NULL);

devfs_unregister (MegaKbd_devfs_dir);
input_unregister_device (&button_dev);
printk ("megaKbd driver uninstalled OK\n");
}

module_init (megaKbd_init);
module_exit (megaKbd_exit);

MODULE_LICENSE ("GPL");
MODULE_AUTHOR ("Kenshinxf <xuefengwang101@gmail.com>");
MODULE_DESCRIPTION ("keyboard driver with spi S3C2410 board");

本来说只写arm就好了,谁知道最后单片机也得我写,真是。。。。

那就写吧,说写,其实就是改改一个师哥以前的单片机程序,不知道其他人为什么就不会呢?自己也没搞过单片机,工作后就直接arm了,其实还是比较简单的

下面是单片机程序:

/**key.c***/

#include <mega88.h>
#include "key.h"

#define INT PORTC.2
unsigned char ScanState = 0;
unsigned char KeyDelay[25];
unsigned char temp0;
bit flag0 = 0;

void SendKeyChar(unsigned char KeyValue)
{
PINC.5 = 1;
//SpiPutChar(KeyValue);
//I2cSendChar(KeyValue);
temp0 = SPSR;
SPDR = KeyValue;
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
INT = 1;
flag0 = 1;
}

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0x80;
switch(ScanState)
{
case 0:
if(Col1Row1 == ROW1)
{
if(Col1Row1 == 0)
{
if(++KeyDelay[0] == 7)
{
KeyDelay[0] = 0;
if(ColRow11)
{
ColRow11 = 0;
SendKeyChar(1);
}
}
}
}
else
{
if(Col1Row1 == 0) SendKeyChar(2);
else
{
KeyDelay[0] = 0;
ColRow11 = 1;
SendKeyChar(3);
}
}
Col1Row1 = ROW1;
if(Col1Row2 == ROW2)
{
if(Col1Row2 == 0)
{
if(++KeyDelay[1] == 7)
{
KeyDelay[1] = 0;
if(ColRow12)
{
ColRow12 = 0;
SendKeyChar(4);
}
}
}
}
else
{
if(Col1Row2 == 0) SendKeyChar(5);
else
{
KeyDelay[1] = 0;
ColRow12 = 1;
SendKeyChar(6);
}
}
Col1Row2 = ROW2;
if(Col1Row3 == ROW3)
{
if(Col1Row3 == 0)
{
if(++KeyDelay[2] == 7)
{
KeyDelay[2] = 0;
if(ColRow13)
{
ColRow13 = 0;
SendKeyChar(7);
}
}
}
}
else
{
if(Col1Row3 == 0) SendKeyChar(8);
else
{
KeyDelay[2] = 0;
ColRow13 = 1;
SendKeyChar(9);
}
}
Col1Row3 = ROW3;
if(Col1Row4 == ROW4)
{
if(Col1Row4 == 0)
{
if(++KeyDelay[3] == 7)
{
KeyDelay[3] = 0;
if(ColRow14)
{
ColRow14 = 0;
SendKeyChar(10);
}
}
}
}
else
{
if(Col1Row4 == 0) SendKeyChar(11);
else
{
KeyDelay[3] = 0;
ColRow14 = 1;
SendKeyChar(12);
}
}
Col1Row4 = ROW4;
if(Col1Row5 == ROW5)
{
if(Col1Row5 == 0)
{
if(++KeyDelay[4] == 7)
{
KeyDelay[4] = 0;
if(ColRow15)
{
ColRow15 = 0;
SendKeyChar(13);
}
}
}
}
else
{
if(Col1Row5 == 0) SendKeyChar(14);
else
{
KeyDelay[4] = 0;
ColRow15 = 1;
SendKeyChar(15);
}
}
Col1Row5 = ROW5;
COL1 = 0;
COL2 = 1;
break;
case 1:
if(Col2Row1 == ROW1)
{
if(Col2Row1 == 0)
{
if(++KeyDelay[5] == 7)
{
KeyDelay[5] = 0;
if(ColRow21)
{
ColRow21 = 0;
SendKeyChar(16);
}
}
}
}
else
{
if(Col2Row1 == 0) SendKeyChar(17);
else
{
KeyDelay[5] = 0;
ColRow21 = 1;
SendKeyChar(18);
}
}
Col2Row1 = ROW1;
if(Col2Row2 == ROW2)
{
if(Col2Row2 == 0)
{
if(++KeyDelay[6] == 7)
{
KeyDelay[6] = 0;
if(ColRow22)
{
ColRow22 = 0;
SendKeyChar(19);
}
}
}
}
else
{
if(Col2Row2 == 0) SendKeyChar(20);
else
{
KeyDelay[6] = 0;
ColRow22 = 1;
SendKeyChar(21);
}
}
Col2Row2 = ROW2;
if(Col2Row3 == ROW3)
{
if(Col2Row3 == 0)
{
if(++KeyDelay[7] == 7)
{
KeyDelay[7] = 0;
if(ColRow23)
{
ColRow23 = 0;
SendKeyChar(22);
}
}
}
}
else
{
if(Col2Row3 == 0) SendKeyChar(23);
else
{
KeyDelay[7] = 0;
ColRow23 = 1;
SendKeyChar(24);
}
}
Col2Row3 = ROW3;
if(Col2Row4 == ROW4)
{
if(Col2Row4 == 0)
{
if(++KeyDelay[8] == 7)
{
KeyDelay[8] = 0;
if(ColRow24)
{
ColRow24 = 0;
SendKeyChar(25);
}
}
}
}
else
{
if(Col2Row4 == 0) SendKeyChar(26);
else
{
KeyDelay[8] = 0;
ColRow24 = 1;
SendKeyChar(27);
}
}
Col2Row4 = ROW4;
if(Col2Row5 == ROW5)
{
if(Col2Row5 == 0)
{
if(++KeyDelay[9] == 7)
{
KeyDelay[9] = 0;
if(ColRow25)
{
ColRow25 = 0;
SendKeyChar(28);
}
}
}
}
else
{
if(Col2Row5 == 0) SendKeyChar(29);
else
{
KeyDelay[9] = 0;
ColRow25 = 1;
SendKeyChar(30);
}
}
Col2Row5 = ROW5;
COL2 = 0;
COL3 = 1;
break;
case 2:
if(Col3Row1 == ROW1)
{
if(Col3Row1 == 0)
{
if(++KeyDelay[10] == 7)
{
KeyDelay[10] = 0;
if(ColRow31)
{
ColRow31 = 0;
SendKeyChar(31);
}
}
}
}
else
{
if(Col3Row1 == 0) SendKeyChar(32);
else
{
KeyDelay[10] = 0;
ColRow31 = 1;
SendKeyChar(33);
}
}
Col3Row1 = ROW1;
if(Col3Row2 == ROW2)
{
if(Col3Row2 == 0)
{
if(++KeyDelay[11] == 7)
{
KeyDelay[11] = 0;
if(ColRow32)
{
ColRow32 = 0;
SendKeyChar(34);
}
}
}
}
else
{
if(Col3Row2 == 0) SendKeyChar(35);
else
{
KeyDelay[11] = 0;
ColRow32 = 1;
SendKeyChar(36);
}
}
Col3Row2 = ROW2;
if(Col3Row3 == ROW3)
{
if(Col3Row3 == 0)
{
if(++KeyDelay[12] == 7)
{
KeyDelay[12] = 0;
if(ColRow33)
{
ColRow33 = 0;
SendKeyChar(37);
}
}
}
}
else
{
if(Col3Row3 == 0) SendKeyChar(38);
else
{
KeyDelay[12] = 0;
ColRow33 = 1;
SendKeyChar(39);
}
}
Col3Row3 = ROW3;
if(Col3Row4 == ROW4)
{
if(Col3Row4 == 0)
{
if(++KeyDelay[13] == 7)
{
KeyDelay[13] = 0;
if(ColRow34)
{
ColRow34 = 0;
SendKeyChar(40);
}
}
}
}
else
{
if(Col3Row4 == 0) SendKeyChar(41);
else
{
KeyDelay[13] = 0;
ColRow34 = 1;
SendKeyChar(42);
}
}
Col3Row4 = ROW4;
if(Col3Row5 == ROW5)
{
if(Col3Row5 == 0)
{
if(++KeyDelay[14] == 7)
{
KeyDelay[14] = 0;
if(ColRow35)
{
ColRow35 = 0;
SendKeyChar(43);
}
}
}
}
else
{
if(Col3Row5 == 0) SendKeyChar(44);
else
{
KeyDelay[14] = 0;
ColRow35 = 1;
SendKeyChar(45);
}
}
Col3Row5 = ROW5;
COL3 = 0;
COL4 = 1;
break;
case 3:
if(Col4Row1 == ROW1)
{
if(Col4Row1 == 0)
{
if(++KeyDelay[15] == 7)
{
KeyDelay[15] = 0;
if(ColRow41)
{
ColRow41 = 0;
SendKeyChar(46);
}
}
}
}
else
{
if(Col4Row1 == 0) SendKeyChar(47);
else
{
KeyDelay[15] = 0;
ColRow41 = 1;
SendKeyChar(48);
}
}
Col4Row1 = ROW1;
if(Col4Row2 == ROW2)
{
if(Col4Row2 == 0)
{
if(++KeyDelay[16] == 7)
{
KeyDelay[16] = 0;
if(ColRow42)
{
ColRow42 = 0;
SendKeyChar(49);
}
}
}
}
else
{
if(Col4Row2 == 0) SendKeyChar(50);
else
{
KeyDelay[16] = 0;
ColRow42 = 1;
SendKeyChar(51);
}
}
Col4Row2 = ROW2;
if(Col4Row3 == ROW3)
{
if(Col4Row3 == 0)
{
if(++KeyDelay[17] == 7)
{
KeyDelay[17] = 0;
if(ColRow43)
{
ColRow43 = 0;
SendKeyChar(52);
}
}
}
}
else
{
if(Col4Row3 == 0) SendKeyChar(53);
else
{
KeyDelay[17] = 0;
ColRow43 = 1;
SendKeyChar(54);
}
}
Col4Row3 = ROW3;
if(Col4Row4 == ROW4)
{
if(Col4Row4 == 0)
{
if(++KeyDelay[18] == 7)
{
KeyDelay[18] = 0;
if(ColRow44)
{
ColRow44 = 0;
SendKeyChar(55);
}
}
}
}
else
{
if(Col4Row4 == 0) SendKeyChar(56);
else
{
KeyDelay[18] = 0;
ColRow44 = 1;
SendKeyChar(57);
}
}
Col4Row4 = ROW4;
if(Col4Row5 == ROW5)
{
if(Col4Row5 == 0)
{
if(++KeyDelay[19] == 7)
{
KeyDelay[19] = 0;
if(ColRow45)
{
ColRow45 = 0;
SendKeyChar(58);
}
}
}
}
else
{
if(Col4Row5 == 0) SendKeyChar(59);
else
{
KeyDelay[19] = 0;
ColRow45 = 1;
SendKeyChar(60);
}
}
Col4Row5 = ROW5;
COL4 = 0;
COL5 = 1;
break;
case 4:
if(Col5Row1 == ROW1)
{
if(Col5Row1 == 0)
{
if(++KeyDelay[20] == 7)
{
KeyDelay[20] = 0;
if(ColRow51)
{
ColRow51 = 0;
SendKeyChar(61);
}
}
}
}
else
{
if(Col5Row1 == 0) SendKeyChar(62);
else
{
KeyDelay[20] = 0;
ColRow51 = 1;
SendKeyChar(63);
}
}
Col5Row1 = ROW1;
if(Col5Row2 == ROW2)
{
if(Col5Row2 == 0)
{
if(++KeyDelay[21] == 7)
{
KeyDelay[21] = 0;
if(ColRow52)
{
ColRow52 = 0;
SendKeyChar(64);
}
}
}
}
else
{
if(Col5Row2 == 0) SendKeyChar(65);
else
{
KeyDelay[21] = 0;
ColRow52 = 1;
SendKeyChar(66);
}
}
Col5Row2 = ROW2;
if(Col5Row3 == ROW3)
{
if(Col5Row3 == 0)
{
if(++KeyDelay[22] == 7)
{
KeyDelay[22] = 0;
if(ColRow53)
{
ColRow53 = 0;
SendKeyChar(67);
}
}
}
}
else
{
if(Col5Row3 == 0) SendKeyChar(68);
else
{
KeyDelay[22] = 0;
ColRow53 = 1;
SendKeyChar(69);
}
}
Col5Row3 = ROW3;
if(Col5Row4 == ROW4)
{
if(Col5Row4 == 0)
{
if(++KeyDelay[23] == 7)
{
KeyDelay[23] = 0;
if(ColRow54)
{
ColRow54 = 0;
SendKeyChar(70);
}
}
}
}
else
{
if(Col5Row4 == 0) SendKeyChar(71);
else
{
KeyDelay[23] = 0;
ColRow54 = 1;
SendKeyChar(72);
}
}
Col5Row4 = ROW4;
if(Col5Row5 == ROW5)
{
if(Col5Row5 == 0)
{
if(++KeyDelay[24] == 7)
{
KeyDelay[24] = 0;
if(ColRow55)
{
ColRow55 = 0;
SendKeyChar(73);
}
}
}
}
else
{
if(Col5Row5 == 0) SendKeyChar(74);
else
{
KeyDelay[24] = 0;
ColRow55 = 1;
SendKeyChar(75);
}
}
Col5Row5 = ROW5;
COL5 = 0;
COL1 = 1;
break;
default:
break;
}
ScanState++;
if(ScanState == 5) ScanState = 0;

}


// Declare your global variables here


void main(void)
{
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif


PORTB=0x00;
DDRB=0x11;


PORTC=0x00;
DDRC=0x24;


PORTD=0x1F;
DDRD=0x60;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7.813 kHz
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected TCCR0A=0x00;
TCCR0B=0x05;
TCNT0=0x80;
OCR0A=0x00;
OCR0B=0x00;


// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;


// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;


// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;


// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x01;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;


// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;


// SPI initialization
// SPI Type: Slave
// SPI Clock Rate: 125.000 kHz
// SPI Clock Phase: Cycle Half
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=0x42;
SPSR=0x00;


// Global enable interrupts
#asm("sei")


while (1)
{
if(flag0)
{
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
flag0 = 0;
INT = 0;
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
INT = 1;
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
#asm("nop")
INT = 0;
}
};
}


/***key.h****/

#define COL1 DDRB.0
#define COL2 DDRB.1
#define COL3 DDRD.7
#define COL4 DDRD.6
#define COL5 DDRD.5

#define ROW1 PIND.0
#define ROW2 PIND.1
//#define KEY1 PIND.2
//#define KEY2 PIND.3
#define ROW3 PIND.2
#define ROW4 PIND.3
#define ROW5 PINB.6

bit Col1Row1 = 1;
bit Col1Row2 = 1;
bit Col1Row3 = 1;
bit Col1Row4 = 1;
bit Col1Row5 = 1;

bit Col2Row1 = 1;
bit Col2Row2 = 1;
bit Col2Row3 = 1;
bit Col2Row4 = 1;
bit Col2Row5 = 1;

bit Col3Row1 = 1;
bit Col3Row2 = 1;
bit Col3Row3 = 1;
bit Col3Row4 = 1;
bit Col3Row5 = 1;

bit Col4Row1 = 1;
bit Col4Row2 = 1;
bit Col4Row3 = 1;
bit Col4Row4 = 1;
bit Col4Row5 = 1;

bit Col5Row1 = 1;
bit Col5Row2 = 1;
bit Col5Row3 = 1;
bit Col5Row4 = 1;
bit Col5Row5 = 1;

bit ColRow11 = 1;
bit ColRow12 = 1;
bit ColRow13 = 1;
bit ColRow14 = 1;
bit ColRow15 = 1;

bit ColRow21 = 1;
bit ColRow22 = 1;
bit ColRow23 = 1;
bit ColRow24 = 1;
bit ColRow25 = 1;

bit ColRow31 = 1;
bit ColRow32 = 1;
bit ColRow33 = 1;
bit ColRow34 = 1;
bit ColRow35 = 1;

bit ColRow41 = 1;
bit ColRow42 = 1;
bit ColRow43 = 1;
bit ColRow44 = 1;
bit ColRow45 = 1;

bit ColRow51 = 1;
bit ColRow52 = 1;
bit ColRow53 = 1;
bit ColRow54 = 1;
bit ColRow55 = 1;

Read More...

星期一, 十二月 10, 2007

s3c2410 _spi概述

概况:

S3C2410X的连续外围设备接口(SPI)能连接电路实现连续数据传递。S3C2410X包含2SPI,,每个都分别有两个8位转移寄存器用于数据的传输和接收。在一个SPI进行数据传递时,同步传送数据并连续输出数据。在某一频率的8位连续数据由它相应的通讯控制寄存器设置所决定。假如你只发送数据,接收数据就能设为哑元。反之,如果你只想接收数据,你应该发送设为哑元'1'数据。

S3C24104个与SPI传输有关的I/O信号引脚:SCK(SPICLK01)MISO(SPIMISOO1)数据线,MOSISPIMOSIO1)和低电平有效的/SS(nSS01)引脚(输入)

特点

SPI协议(Ver.2.11)兼容

8位移位寄存器输出

8位移位寄存器接收

8位预分频逻辑

查询,中断,DMA传输模式

 

 

SPI操作

采用SPI接口, S3C2410X可发送/接收与外部设备同步的8位数据。一个串行时钟线与两条用来移位和采样信息的数据线同步。 SPI为主机时,发送频率可以通过为SPPREn寄存器设置合适的值来控制。你可以通过调整波特率数据寄存器的值来修改它的频率。当SPI为从机时,其它的主机提供时钟。当编程者向SPTDATn寄存器写字节数据时,SPI的收/发将会同时开始。在其它情况下,在向SPTDATn寄存器写入字节数据时要把nSS激活。

 

编辑程序

 

当向SPTDATn寄存器写入字节时,如果ENSCKSPCONn被设置的话,SPI就开始传输

你可以使用一上典型的程序来操作一个SPI卡。

编程SPI模式,基本遵循这些基本步骤:

1.       设置波特率寄存器(SPPREn

2.       设置SPCONn以选择合适的SPI模式。

3.        写数据0xFFSPTDATn10次以初始化MMCSD卡。.

4.       设置GPIO引脚使其具有nSS功能,低电平时使MMCSD卡有效。

5.       发送数据:检查发送准备樗是否为1,如果为1 的话就开始向SPTDATn写数据。

6.       接收数据(1):SPCONn TAGD 位禁用 = 正常模式

    :向SPTDATn 0xFF,然后测试REDY,再从读缓存中读取数据。

7.       接收数据:SPCONnTAGD 能用 = 自动接收垃圾数据模式。

    :测试REDY,然后从读缓存中读取数据。

8.       设置GPIO引脚使其具有nSS功能,高电平时使MMCSD卡有效。

 

 

通过DMA发送的步骤

1.       SPI的配置为DMA模式

2.       DMA合适设置

3.       SPI请求DMA服务

4.       DMASPI发送一个字节数据.

5.        SPI向卡里发送数据

6.       返回到步骤3直到DAM计数变为0

7.       SMOD位把SPI设置为中断或查询模式

 

通过DMA接收的步骤

1.       SPI设置为DMASMOD位开始,并且设置TAGD.

2.       全适配置 DMA

3.       SPI从卡里接收一字节数据

4.       SPI请求DMA服务

5.       DMASPI接收数据

6.        自动的向SPIDATn写数据0xFF

7.        回到步骤4DAM计数变为0

8.       SMOD位把SPI配置为查询模式,并且清TAGD

9.       如果SPSTAnREDY 标志被设置,就读取最后的字节数据

 

:

总接收的数据 = DAM TC +在查询模式下的最后值.

DAM接收的第一个数据是哑元,所以使用者可以忽略它

SPI 从机接收模式和B模块

 

如果SPI从机接收模式有效和SPI模块被设成B模块,SPI操作将会失败。

READY信号这一内部信号将在SPI_CNT达到0之前变成高电平。因此,在DMA模式中,DATA_READ信号应该在最后一个数据结束之前产生。

注意

1)      DMA模式:这种模式不能在SPI从机接收模式和B模块下使用。

2)      查询模式:在SPI从机接收模式和B模块下DATA_READ信号应该推迟SPICLK的一个相位。

3)      中断模式:在SPI从机接收模式和B模块下DATA_READ信号应该推迟SPICLK的一个相位。

SPI特殊寄存器

SPI控制寄存器

SPI状态寄存器

SPI引脚控制寄存器

如果SPI系统使能时,除nSS引脚外的其它引脚的方向通过SPCONnMSTR位来控制。nSS引脚的方向总是输入。

SPI为主机时,nSS引脚用来检查由SPPINENMUL位提供的多主机错误信号,另一个GPIO应该选择从机。

如果SPI被设置为从机,nSS引脚奖被一个主机选择为从机。

SPIMISOSPIMOSI数据引脚用来发送和接收串行数据。当SPI为主机时,SPIMISO是数据输入引脚,SPIMOSI是数据输出引脚,SPICLKSCK)是时钟输出线。当SPI为从机时,这些引脚执行相反的功能。在多主机系统中,SPICLKSCK)、SPIMOSISPIMISO将被分别的配置在一个体系中。

当其它的SPI设备作为从机选择S3C2410 SPI为从机时,一个主机SPI可以发出一个多主机错误信号。当这个信号被探测到,将会立刻发生下面所说的事情。但是如果你想探测到这种信号的话必须事先设置SPPINnENMUL位。

 

1.       SPCONnMSTR位被强制为0来启动从机模式。

2.       SPSTAnMULF标志位被置位,一个SPI中断会产生。

概况:

S3C2410X的连续外围设备接口(SPI)能连接电路实现连续数据传递。S3C2410X包含2SPI,,每个都分别有两个8位转移寄存器用于数据的传输和接收。在一个SPI进行数据传递时,同步传送数据并连续输出数据。在某一频率的8位连续数据由它相应的通讯控制寄存器设置所决定。假如你只发送数据,接收数据就能设为哑元。反之,如果你只想接收数据,你应该发送设为哑元'1'数据。

S3C24104个与SPI传输有关的I/O信号引脚:SCK(SPICLK01)MISO(SPIMISOO1)数据线,MOSISPIMOSIO1)和低电平有效的/SS(nSS01)引脚(输入)

特点

SPI协议(Ver.2.11)兼容

8位移位寄存器输出

8位移位寄存器接收

8位预分频逻辑

查询,中断,DMA传输模式

 

 

SPI操作

采用SPI接口, S3C2410X可发送/接收与外部设备同步的8位数据。一个串行时钟线与两条用来移位和采样信息的数据线同步。 SPI为主机时,发送频率可以通过为SPPREn寄存器设置合适的值来控制。你可以通过调整波特率数据寄存器的值来修改它的频率。当SPI为从机时,其它的主机提供时钟。当编程者向SPTDATn寄存器写字节数据时,SPI的收/发将会同时开始。在其它情况下,在向SPTDATn寄存器写入字节数据时要把nSS激活。

Read More...