在51单片机上写外围设备的驱动有必要么?
打算给C8051F040的一些外围器件(ADC, SMBUS, UART,...)写驱动并提供统一的数据传输接口(并向上封装到能给外围器件分配虚拟寻址地址的层次),但是这大大增加了ISR的执行时间和接口函数的额外空间。想知道各位大大是如何考虑的。 这个应该看系统的大小和实际需求吧。单片机本来就是精简。 出于锻炼自己编程能力的角度考虑是挺好的。 支持一下来,新人 取决于你要做什么,你以都用这个系列的芯片还是就是练习,或者你想造福后人?
做外围驱动很锻炼模块化设计,还有时序的控制。所以看你的需求了 severewinner 发表于 2014-9-4 10:40
取决于你要做什么,你以都用这个系列的芯片还是就是练习,或者你想造福后人?
做外围驱动很锻炼模块化设计 ...
看起来还是练习的成分多一点。。
那就当作多了解下这方面的知识,再请大大帮看下代码。。
UART
#include "uart.h"
unsigned char idata UART0_Stat;//BUSY:1
unsigned char idata UART0_DevAdd;
unsigned char xdata* idata UART0_TxCache;
unsigned char idata UART0_TxLen;
unsigned char xdata* idata UART0_RxCache;
unsigned char idata UART0_RxLen;
/*
TransmissionCache:
if Multiprocessor Communications
the UART0_DevAdd is the Target Address
or it would be blank
UART0_TxCache is the data pointer
UART0_RxLen is the data's length
ReceptionCache:
*/
Status UART0_O(unsigned char DevAdd, unsigned char xdata* TxCache, unsigned char TxLen){
if( UART0_Stat & UART0_Busy ) return 0; //Fail|Buf_full;
SFRPAGE_SAVED = SFRPAGE;
SFRPAGE = UART0_PAGE;
UART0_Stat |= UART0_Busy;
UART0_DevAdd = DevAdd;
UART0_TxCache = TxCache;
UART0_TxLen = TxLen;
SBUF0 = *UART0_TxCache++;
UART0_TxLen--;
SFRPAGE = SFRPAGE_SAVED;
return 1; //complete|sending;
}
void UART0_Interrupt(void) interrupt 4 {
if ( RI0 == 1 ){
RI0 = 0;
*UART0_RxCache++ = SBUF0;//*UART0_RxCache point to the next position of a string's tail
UART0_RxLen++;
}
if( TI0 == 1 ){
TI0 = 0;
if( UART0_TxLen != 0 ){
SBUF0 = *UART0_TxCache++;
UART0_TxLen--;
}else{
UART0_Stat &= ~UART0_Busy;
}
}
return ;
}
一个简单的UART驱动,和一个相对复杂的SMBUS驱动
#include "smbus.h"
#include "gernic.h"
unsigned char idata SMBUS0_Stat;//BUSY:1 RnW:1
unsigned char idata SMBUS0_DevAdd;
unsigned char xdata* idata SMBUS0_AddCache;
unsigned char idata SMBUS0_AddLen;
unsigned char xdata* idata SMBUS0_TxRxCache;
unsigned char idata SMBUS0_TxRxLen;
Status SMBUS0_IO(uint8 DevAdd, unsigned char xdata *AddCache, unsigned char xdata *TxRxCache, uint8 AddLen, uint8 TxRxLen){
if( SMBUS0_Stat & SMBUS0_Busy ) return 0; //Fail|Buf_full;
SMBUS0_Stat |= SMBUS0_Busy;//置位忙
if( (DevAdd & 0x01) == READ){
SMBUS0_Stat |= READ;
}else{
SMBUS0_Stat |= WRITE;
}
SMBUS0_DevAdd = DevAdd & 0xFE;//放入目标地址和写操作
SMBUS0_AddCache = AddCache;//放入目标数据位置
SMBUS0_TxRxCache = TxRxCache;//放入数据地址
SMBUS0_AddLen = AddLen;//放入地址长度
SMBUS0_TxRxLen = TxRxLen;//放入数据长度
SFRPAGE_SAVED = SFRPAGE;//开始发送
SFRPAGE = SMB0_PAGE;
STA = 1;
SFRPAGE = SFRPAGE_SAVED;
return 1; //complete|sending;
}
void SMBUS0_ISR (void) interrupt 7 {
SI = 0;
switch( SMB0STA ){
case SMB_MSTART ://发送了开始位 ok
case SMB_MRPSTART ://发送了重新开始位 ok
SMB0DAT = SMBUS0_DevAdd; //发送目标地址
STA = 0;//清零STA
break;
case SMB_MTADDACK : //发送目标地址收到ACK
case SMB_MTDBACK : //发送数据收到ACK
if( SMBUS0_AddLen != 0 ){//要发送地址
SMB0DAT = *SMBUS0_AddCache++;
SMBUS0_AddLen--;
break;
}
if( (SMBUS0_Stat & READ) == READ ){
SMBUS0_Stat |= READ;
STA = 1;//发送重复开始
break;
}
if( SMBUS0_TxRxLen != 0 ){//要发送的数据
SMB0DAT = *SMBUS0_TxRxCache++;
SMBUS0_TxRxLen--;
break;
}
STO = 1;//结束传输
SMBUS0_Stat &= ~SMBUS_BUSY;//SMBUS闲
break;
case SMB_MRDBACK :
*SMBUS0_TxRxCache++ = SMB0DAT;
case SMB_MRADDACK :
if( --SMBUS0_TxRxLen != 0 ){ //接收完毕?
AA = 1;
}else{
AA = 0;
}
break;
case SMB_MRDBNACK :
*SMBUS0_TxRxCache = SMB0DAT;
STO = 1;
SMBUS0_Stat &= ~SMBUS0_Busy;
break;
default:
SMB0CN &= ~0x74; //重设
SMB0CN |= 0x40;
}
return ;
}
是否用汇编写,接口用Blocking还是Non-Blocking,可以精简信号传递么,在这些方面尚有疑问。
简而言之就是还是想找明灯讨个最优化设计的大概信息,就练习模块化设计而言。
页:
[1]