|
发表于 2010-11-24 23:58:03
|
显示全部楼层
you can significantly improve many of the examples in the book.
for example, here is your hc164 code:
======original code===========
/***************************************************
* 大量宏定义,便于代码移植和阅读
***************************************************/
#define HIGH 1
#define LOW 0
#define LS164_DATA(x) {if((x))P0_4=1;else P0_4=0;}
#define LS164_CLK(x) {if((x))P0_5=1;else P0_5=0;}
#define SEG_PORT P0 //控制数码管字型码端口
/****************************************
*函数名称:LS164Send
*输入:无
*输出:无
*功能:74LS164 发送单个字节
******************************************/
void LS164Send(unsigned char byte)
{
unsigned char j;
for(j=0;j<=7;j++)//对输入数据进行移位检测
{
if(byte&(1<<(7-j))) //检测字节当前位
{
LS164_DATA(HIGH); //串行数据输入引脚为高电平
}
else
{
LS164_DATA(LOW); //串行数据输入引脚为低电平
}
LS164_CLK(LOW); //同步时钟输入端以一个上升沿结束确定该位的值
LS164_CLK(HIGH);
}
}
/*******
======end code========
a few issues with it:
1) the code isn't very portable: you have hard-coded DATA on P0.4 and SCK on P0.5. to the extent that you want to change it, you have to recode the macros and then their initialization portion - to make them into the output mode (should you port the code to a chip with DDR).
2) the hc164 portion of the code isn't efficient.
a better approach is to define the port the data/sck pins are on and then write to those pins LOGICALLY.
here is an example:
========alternative header=============
#define SPI_PORT P2
#define SPI_PORT_IN P2
#define SPI_DDR P2
//#define SPI_CS (1<<0)
#define SPI_SCK (1<<0) //serial clock
#define SPI_MOSI (1<<3) //mask out slave in
#define SPI_MISO (1<<1) //master in slave out
#define SPI_DLY 0
#define SPI_DELAY(n) delay(n) //some delay
#define SPI_SELECT(cs) {IO_CLR(SPI_PORT, cs); SPI_DELAY(SPI_DLY); IO_OUT(SPI_DDR, cs);} //select the chip
#define SPI_DESELECT(cs) {IO_SET(SPI_PORT, cs); SPI_DELAY(SPI_DLY); IO_OUT(SPI_DDR, cs);} //deselect the chip
#define spi_select(cs) SPI_SELECT(cs) //select the spi attached to cs pin
#define spi_deselect(cs) SPI_DESELECT(cs) //deselect the spi attached to cs pin
void spi_init(void); //initialize the spi
void spi_send(unsigned char data_t); //send data_t over spi
unsigned char spi_read(void); //read data from spi
=========end header================
========alternative source========
void spi_init(void) {
IO_IN(SPI_DDR, SPI_MISO); //input pins
IO_CLR(SPI_PORT, SPI_SCK | SPI_MOSI); //clear output pins
//IO_SET(SPI_PORT, cs); //unselect the chip
IO_OUT(SPI_DDR, SPI_SCK | SPI_MOSI); //set pins as output
}
//data strobe out on the rising edge of sck
void spi_send(unsigned char data_t) {
unsigned char mask = 0x80; //start with the most signifcant bit
//IO_CLR(SPI_PORT, SPI_SCK); //default state of sck: low
while (mask) {
IO_CLR(SPI_PORT, SPI_SCK); //clear spi_sck
if (data_t & mask) IO_SET(SPI_PORT, SPI_MOSI); //send the data
else IO_CLR(SPI_PORT, SPI_MOSI);
IO_SET(SPI_PORT, SPI_SCK); //send on the rising edge
//SPI_DELAY(SPI_DLY); //insert some delays to generate 50% dc
mask = mask >> 1; //next bit
}
//IO_CLR(SPI_PORT, SPI_MOSI); //clear mosi
IO_CLR(SPI_PORT, SPI_SCK);
}
======end alternative==========
so if you were to change the pin assignment, you just need to redefine _SCK, _MOSI or _MISO and the code will work.
or if you wish to send multi-bytes or odd bits over spi, you can modify the mask variable in the spi_send() routine to achieve that.
many (most) of your code pieces in the book can benefit from this approach. |
|