我用的芯片比较杂,再加上记性不好,只要放下几天就全忘了,想再继续写又得重新看手册,所以一般情况下我都会把驱动部分封装成文件,对外基本上统一接口,而不必再关心实现的细节,这样用起来就比较方便了。既是学习又是总结,虽然该忘还是忘,但好歹留下个印记再拾起来就能快一些。下面就把我的代码贴出来,有的是我自己写的,有的是直接拷贝过来的,都揉到了一起,需要的话可以拿过来直接使用,不全的地方也可以随时加进去。
文件共有4个,两个.c和两个 .h文件。和51相关的叫HAL.*,和迪文屏相关的叫ASIC.*。
1.HAL.*,定义了一些常量和功能函数的定义。为了减小程序的体积,每个功能都使用宏定义来打开或关闭,没有用到的功能关掉就不参与编译了。
HAL.h
- #ifndef _HAL_H_
- #define _HAL_H_
- #include
- #include
- #include
- #include "T5L_OS_8051.h"
- #include "T5L0_CFG.h"
-
- typedef unsigned char u8;
- typedef unsigned int u16;
- typedef unsigned long u32;
- typedef signed char s8;
- typedef signed short s16;
- typedef signed long s32;
-
- extern void System_Init(void);
- extern u32 SystickCount(void);
- extern void Delay10US(u16 Count);
- extern void DelayMS(u16 MS);
- #ifdef HW_GPIO
- #define IN 0
- #define OUT 1
- #define LOW 0
- #define HIGH 1
-
- extern void GPIO_Config(u8 Port, u8 Pin, u8 Dir);
- #endif
- #ifdef HW_UART
- typedef void (*TISR_UART)(u8 DAT);
-
- extern void UART_Init(u8 UARTx, TISR_UART OnUART);
- extern void UART_Free(u8 UARTx);
- extern void UART_Start(u8 UARTx);
- extern void UART_Stop(u8 UARTx);
- extern void UART_Config(u8 UARTx, u32 BaudRate, u8 DataBit);
- extern void UART_SendByte(u8 UARTx, u8 DAT);
- extern void UART_SendBytes(u8 UARTx, u8* Data, u16 Size);
- #endif
- #ifdef HW_TIM
- #endif
- #ifdef HW_RTC
- #endif
- #ifdef HW_WDT
- extern void WDT_Init(u8 S);
- extern void WDT_Start(void);
- extern void WDT_Stop(void);
- extern void WDT_Feed(void);
- #endif
- #ifdef HW_ADC
- #endif
- #ifdef HW_PWM
- #endif
- #ifdef HW_I2C
- #endif
- #ifdef HW_SPI
- #endif
- #ifdef HW_CAN
- #endif
- #ifdef HW_FLASH
- extern void FLASH_Read(u16 Reg, u32 Addr, u16 Size);
- extern void FLASH_Write(u16 Reg, u32 Addr, u16 Size);
- #endif
-
- #endif
复制代码
HAL.c
- #include "HAL.h"
- /*CPU*************************************************************************/
- #define FOSC 206438400UL //系统主频,1ms=(65536-FOSC/12/1000)
- static idata u16 _Delay = 0;
- static idata u32 SysTick = 0;
- static void Delay_Init(void) //占用TIM2
- {
- T2CON = 0x70;
- TH2 = 0x00;
- TL2 = 0x00;
- TRL2H = 0xBC; //1ms的定时器
- TRL2L = 0xCD;
- //TRL2H = 0xFF; //10us的定时器
- //TRL2L = 0x54;
- IEN0 |= 0x20; //启动定时器2
- TR2 = 0x01;
- EA = 1;
- }
- static void ISR_TIM2(void) interrupt 5
- {
- TF2 = 0; //清除定时器2的中断标志位
- SysTick++;
- }
- void Delay10US(u16 Count)
- {
- _Delay = Count;
- while (_Delay) ;
- }
- void DelayMS(u16 MS)
- {
- //Delay10US(MS * 100);
- u32 _SysTick = SysTick;
- while ((SysTick - _SysTick) < MS) ;
- }
- u32 SysTickCount(void)
- {
- return SysTick;
- }
- void System_Init(void)
- {
- EA = 0;
- RS0 = 0;
- RS1 = 0;
- CKCON = 0x00;
- T2CON = 0x70;
- DPC = 0x00;
- PAGESEL = 0x01;
- D_PAGESEL = 0x02; //DATA RAM 0x8000-0xFFFF
- MUX_SEL = 0x00; //UART2,UART3,CAN,WDT关闭
- RAMMODE = 0x00;
- PORTDRV = 0x01; //驱动强度+/-8mA
-
- IEN0 = 0x00; //关闭所有中断
- IEN1 = 0x00;
- IEN2 = 0x00;
- IP0 = 0x00; //中断优先级默认
- IP1 = 0x00;
- EA = 1;
- Delay_Init();
- }
- /*CPU*************************************************************************/
- /*GPIO************************************************************************/
- #ifdef HW_GPIO
- void GPIO_Config(u8 Port, u8 Pin, u8 Dir)
- {
- u8 Bit = (0x1 << Pin);
-
- switch (Port)
- {
- case 0: if (Dir) P0MDOUT |= Bit; else P0MDOUT &= ~Bit; break;
- case 1: if (Dir) P1MDOUT |= Bit; else P1MDOUT &= ~Bit; break;
- case 2: if (Dir) P2MDOUT |= Bit; else P2MDOUT &= ~Bit; break;
- case 3: if (Dir) P3MDOUT |= Bit; else P3MDOUT &= ~Bit; break;
- }
- }
- static void EX0_ISR_PC(void) interrupt 0
- {
- EA = 0;
- //Code
- EA = 1;
- }
- static void EX1_ISR_PC(void) interrupt 2
- {
- EA = 0;
- //Code
- EA = 1;
- }
- #endif
- /*GPIO************************************************************************/
- /*UART************************************************************************/
- #ifdef HW_UART
- xdata TISR_UART FOnU2, FOnU3, FOnU4, FOnU5;
- xdata u8 BusyT2, BusyT3, BusyT4, BusyT5, EnabledU2, EnabledU3;
- void UART_Init(u8 UARTx, TISR_UART OnUART)
- {
- switch (UARTx)
- {
- case 2: MUX_SEL |= 0x40; GPIO_Config(0, 4, OUT); GPIO_Config(0, 5, IN); ES2 = 1; BusyT2 = 0; EnabledU2 = 0; FOnU2 = OnUART; break;
- case 3: MUX_SEL |= 0x20; GPIO_Config(0, 6, OUT); GPIO_Config(0, 7, IN); IEN2 |= 1; BusyT3 = 0; EnabledU3 = 0; FOnU3 = OnUART; break;
- case 4: SCON4T |= 0x80; SCON4R |= 0x80; IEN1 |= 0x0C; BusyT4 = 0; FOnU4 = OnUART; break; //使能TxRx
- case 5: SCON5T |= 0x80; SCON5R |= 0x80; IEN1 |= 0x30; BusyT5 = 0; FOnU5 = OnUART; break;
- default: return ;
- }
- }
- void UART_Free(u8 UARTx)
- {
- switch (UARTx)
- {
- case 2: MUX_SEL &= 0xDF; break; //P0.4,P0.5
- case 3: MUX_SEL &= 0xBF; break; //P0.6,P0.7
- case 4: SCON4T &= 0x7F; SCON4R &= 0x7F; break;
- case 5: SCON5T &= 0x7F; SCON5R &= 0x7F; break;
- default: return ;
- }
- }
- void UART_Config(u8 UARTx, u32 BaudRate, u8 DataBit)
- {
- u16 DIV = 0;
-
- switch (UARTx)
- {
- case 2:
- ADCON = 0x80;
- DIV = 1024 - (FOSC / 64 / BaudRate);
- SREL2H = (u8)(DIV >> 8);
- SREL2L = (u8)(DIV & 0xFF);
- break;
- case 3:
- //SCON3 = 0xD0;
- /*switch (DataBit)
- {
- case 8: SCON1 |= 0x80; break;
- case 9: SCON1 &= 0x7F; break;
- }*/
- DIV = 1024 - (FOSC / 32 / BaudRate);
- SREL3H = (u8)(DIV >> 8);
- SREL3L = (u8)(DIV & 0xFF);
- break;
- case 4:
- /*switch (DataBit)
- {
- case 8: SCON2T &= 0xBF; break;
- case 9: SCON2T |= 0x40; break;
- }*/
- DIV = FOSC / 8 / BaudRate;
- BODE4_DIV_H = (u8)(DIV >> 8);
- BODE4_DIV_L = (u8)(DIV & 0xFF);
- break;
- case 5:
- /*switch (DataBit)
- {
- case 8: SCON3T &= 0xBF; break;
- case 9: SCON3T |= 0x40; break;
- }*/
- DIV = FOSC / 8 / BaudRate;
- BODE5_DIV_H = (u8)(DIV >> 8);
- BODE5_DIV_L = (u8)(DIV & 0xFF);
- break;
- default: return ;
- }
- }
- void UART_Start(u8 UARTx)
- {
- switch (UARTx)
- {
- case 2: SCON2 = 0x50; EnabledU2 = 1; break;
- case 3: SCON3 = 0xD0; EnabledU3 = 1; break;
- case 4: SCON4R |= 0x80; SCON4T |= 0x80; break;
- case 5: SCON5R |= 0x80; SCON5T |= 0x80; break;
- }
- }
- void UART_Stop(u8 UARTx)
- {
- switch (UARTx)
- {
- case 2: EnabledU2 = 0; break;
- case 3: EnabledU3 = 0; break;
- case 4: SCON4R &= 0x7F; SCON4T &= 0x7F; break;
- case 5: SCON5R &= 0x7F; SCON5T &= 0x7F; break;
- }
- }
- void UART_SendByte(u8 UARTx, u8 DAT)
- {
- switch (UARTx)
- {
- case 2: while (BusyT2) ; BusyT2 = 1; SBUF2 = DAT; break;
- case 3: while (BusyT3) ; BusyT3 = 1; SBUF3 = DAT; break;
- case 4: while (BusyT4) ; BusyT4 = 1; SBUF4_TX = DAT; break;
- case 5: while (BusyT5) ; BusyT5 = 1; SBUF5_TX = DAT; break;
- default: return ;
- }
- }
- void UART_SendBytes(u8 UARTx, u8* Data, u16 Size)
- {
- while (Size--) UART_SendByte(UARTx, *Data++);
- }
- static void ISR_UART2(void) interrupt 4
- {
- EA = 0;
- if (RI2)
- {
- RI2 = 0;
- if (EnabledU2 && FOnU2) FOnU2(SBUF2);
- }
- if (TI2 == 1)
- {
- TI2 = 0;
- BusyT2 = 0;
- }
- EA = 1;
- }
- static void ISR_UART3(void) interrupt 16
- {
- EA = 0;
- if (SCON3 & 0x01)
- {
- SCON3 &= 0xFE;
- SCON3 &= 0xFE;
- if (EnabledU3 && FOnU3) FOnU3(SBUF3);
- }
- if (SCON3 & 0x02)
- {
- SCON3 &= 0xFD;
- SCON3 &= 0xFD;
- BusyT3 = 0;
- }
- EA = 1;
- }
- static void ISR_UART4T(void) interrupt 10
- {
- EA = 0;
- SCON4T &= 0xFE;
- BusyT4 = 0;
- EA = 1;
- }
- static void ISR_UART4R(void) interrupt 11
- {
- EA = 0;
- SCON4R &= 0xFE;
- if (FOnU4) FOnU4(SBUF4_RX);
- EA = 1;
- }
- static void ISR_UART5T(void) interrupt 12
- {
- EA = 0;
- SCON5T &= 0xFE;
- BusyT5 = 0;
- EA = 1;
- }
- static void ISR_UART5R(void) interrupt 13
- {
- EA = 0;
- SCON5R &= 0xFE;
- if (FOnU5) FOnU3(SBUF5_RX);
- EA = 1;
- }
- #endif
- /*UART************************************************************************/
- /*TIM*************************************************************************/
- #ifdef HW_TIM
- /*void TIM_Init(u8 TIMx)
- {
- switch (TIMx)
- {
- case 0: TMOD |= 0x01; break;
- case 1: TMOD |= 0x10; break;
- case 2: break;
- }
- }
- void TIM_Free(u8 TIMx)
- {
-
- }
- void TIM_Config(u8 TIMx)
- {
-
- }
- void TIM_Start(u8 TIMx, u16 IntervalMS)
- {
- //TH0 = T1MS >> 8; //1ms定时器
- //TL0 = T1MS;
- ET0 = 1; //开TIM0中断
- //EA = 1; //开总中断
- TR0 = 1; //开启定时器
- }
- void TIM_Stop(u8 TIMx)
- {
-
- }
- static void ISR_TIM0(void) interrupt 1
- {
-
- }
- static void ISR_TIM1(void) interrupt 3
- {
-
- }*/
- #endif
- /*TIM*************************************************************************/
- /*RTC*************************************************************************/
- #ifdef HW_RTC
- #endif
- /*RTC*************************************************************************/
- /*WDT*************************************************************************/
- #ifdef HW_WDT
- void WDT_Init(u8 S)
- {
- u32 Value = S * FOSC;
-
- MUX_SEL &= 0xFD; //配置WDT溢出时间前,关闭WDT
-
- ADR_H = 0xFF;
- ADR_M = 0x00;
- ADR_L = 0x1B;
- RAMMODE = 0x8F;
- DATA3 = (Value >> 24); //WDT溢出时间=0xFF001B值/CPU主频
- DATA2 = (Value >> 16); //206.4384MHz下,0x0C4E0000为1秒
- DATA1 = (Value >> 8);
- DATA0 = (Value & 0xFF);
- APP_EN = 1;
- while (APP_EN == 1) ;
- RAMMODE = 0x00;
- }
- void WDT_Start(void)
- {
- MUX_SEL |= 0x02; //开启WDT
- }
- void WDT_Stop(void)
- {
- MUX_SEL &= 0xFD;
- }
- void WDT_Feed(void)
- {
- MUX_SEL |= 0x01;
- }
- #endif
- /*WDT*************************************************************************/
- /*ADC*************************************************************************/
- #ifdef HW_ADC
- #endif
- /*ADC*************************************************************************/
- /*PWM*************************************************************************/
- #ifdef HW_PWM
- #endif
- /*PWM*************************************************************************/
- /*I2C*************************************************************************/
- #ifdef HW_I2C
- #endif
- /*I2C*************************************************************************/
- /*SPI*************************************************************************/
- #ifdef HW_SPI
- #endif
- /*SPI*************************************************************************/
- /*CAN*************************************************************************/
- #ifdef HW_CAN
- static void ISR_CAN(void) interrupt 9
- {
-
- }
- #endif
- /*CAN*************************************************************************/
- /*FALSH*************************************************************************/
- #ifdef HW_FLASH
- static T5L_Wait(u16 Reg)
- {
- ADR_H = 0x00;
- ADR_M = (u8)(Reg >> 8);
- ADR_L = (u8)(Reg);
- ADR_INC = 0x00;
- do
- {
- for (Reg = 0; Reg <1000; Reg++) DATA2 = DATA1; //释放变量空间一段时间
- RAMMODE = 0xAF;
- while (APP_ACK == 0) ;
- APP_EN = 1;
- while (APP_EN == 1) ;
- RAMMODE = 0x00;
- }
- while (DATA3 ! = 0);
- }
- static T5L_FLASH(u8 Mode, u16 Reg, u32 Addr, u16 Size)
- {
- ADR_H = 0x00;
- ADR_M = 0x00;
- ADR_L = 0x04;
- ADR_INC = 0x01;
- RAMMODE = 0x8F; //启动读Flash
- while (APP_ACK == 0) ;
-
- DATA3 = Mode;
- DATA2 = (u8)(Addr >> 16);
- DATA1 = (u8)(Addr >> 8);
- DATA0 = (u8)(Addr & 0xFE);
- APP_EN = 1;
- while (APP_EN == 1);
-
- DATA3 =(u8)(REG >> 8);
- DATA2 =(u8)(REG & 0xFE);
- DATA1 =(u8)(Size >> 8);
- DATA0 =(u8)(Size & 0xFE);
- APP_EN = 1;
- while (APP_EN == 1);
-
- RAMMODE = 0x00;
- T5L_Wait(0x0004);
- }
- void FLASH_Read(u16 Reg, u32 Addr, u16 Size)
- {
- T5L_FLASH(0x5A, Reg, Addr, Size);
- }
- void FLASH_Write(u16 Reg, u32 Addr, u16 Size)
- {
- T5L_FLASH(0xA5, Reg, Addr, Size);
- }
- #endif
- /*FALSH*************************************************************************/
复制代码
可以自己定义一个.h文件,里面写成这个样子:
#ifndef _T5L0_CFG_H
#define _T5L0_CFG_H
#define HW_GPIO
#define HW_UART
#define HW_TIM
#define HW_WDT
//#define HW_ADC
#define HW_RTC
//#define HW_SPI
//#define HW_I2C
//#define HW_PWM
//#define HW_FLASH
#define SW_MSG
//#define SW_TIM
#define SW_GPIO
#define SW_I2C
#endif
注释掉的功能都是关闭的,需要的话再打开。这个文件可以由用户修改,所以它不包含在HAL.*中。
2.ASIC.*,目前的功能很少,就是读写屏幕的函数,抄来的代码,可以参考其他开发者的例程。
ASIC.h
- #ifndef _ASIC_H_
- #define _ASIC_H_
- #include "HAL.h"
- extern void DGUS_ReadVP(u16 Reg, u8* Data, u16 Size);
- extern void DGUS_WriteVP(u16 Reg, u8* Data, u16 Size);
- typedef enum
- {
- SHAPE_TYPE_RECT = 0x0003,
- SHAPE_TYPE_FILL = 0x0004,
- } SHAAPE_TYPE;
-
- typedef struct
- {
- u16 StartX;
- u16 StartY;
- u16 EndX;
- u16 EndY;
- u16 Color;
- } SHAPE_RECT;
-
- extern u16 Shape_Rect(u16* Data, SHAPE_RECT* Rect, u16 Count, u8 Filled);
-
- #endif
复制代码
ASIC.c
- #include "ASIC.h"
- void DGUS_ReadVP(u16 Reg, u8* Data, u16 Size)
- {
- u8 I = (u8)(Reg & 0x01);
- Reg = Reg / 2;
- ADR_H = 0x00;
- ADR_M = (u8)(Reg>>8);
- ADR_L = (u8)(Reg);
- ADR_INC = 0x01;
- RAMMODE = 0xAF;
- while (APP_ACK == 0);
-
- while (Size > 0)
- {
- APP_EN = 1;
- while (APP_EN == 1) ;
-
- if ((I == 0) && (Size > 0))
- {
- *Data++ = DATA3;
- *Data++ = DATA2;
- I = 1;
- Size--;
- }
- if ((I == 1) && (Size > 0))
- {
- *Data++ = DATA1;
- *Data++ = DATA0;
- I = 0;
- Size--;
- }
- }
- RAMMODE=0x00;
- }
- void DGUS_WriteVP(u16 Reg, u8* Data, u16 Size)
- {
- u8 I = (u8)(Reg & 0x01);
-
- Reg >>= 1;
- ADR_H = 0x00;
- ADR_M = (u8)(Reg >> 8);
- ADR_L = (u8)Reg;
- ADR_INC = 0x01;
- RAMMODE = 0x8F;
- while (APP_ACK == 0) ;
-
- if (I && (Size > 0))
- {
- RAMMODE = 0x83;
- DATA1 = *Data++;
- DATA0 = *Data++;
- APP_EN = 1;
- Size--;
- }
- RAMMODE = 0x8F;
-
- while (Size >= 2)
- {
- DATA3 = *Data++;
- DATA2 = *Data++;
- DATA1 = *Data++;
- DATA0 = *Data++;
- APP_EN = 1;
- Size -= 2;
- }
- if (Size)
- {
- RAMMODE = 0x8C;
- DATA3 = *Data++;
- DATA2 = *Data++;
- APP_EN = 1;
- }
- RAMMODE = 0x00;
- }
- u16 Shape_Rect(u16* Data, SHAPE_RECT* Rect, u16 Count, u8 Filled)
- {
- u16 I = 2, J = 0;
-
- Data[0] = Filled ? SHAPE_TYPE_FILL : SHAPE_TYPE_RECT;
- Data[1] = Count;
- do
- {
- Data[I++] = Rect[J].StartX;
- Data[I++] = Rect[J].StartY;
- Data[I++] = Rect[J].EndX;
- Data[I++] = Rect[J].EndY;
- Data[I++] = Rect[J].Color;
- } while (J++ < Count);
- Data[I] = 0xFF00;
-
- return I;
- }
-
复制代码
如果愿意,可以把屏幕所有的控件都封装进来。但是这个工作量巨大,我是懒得写了,需要什么自己添加吧。
前几天刚做了一个使用OTP芯片的项目,为了降低成本,选用的型号RAM只有48字节,ROM也只有1K,写起程序来一字节一字节往下扣。这种封装方式肯定不行了,换了一种写法才把全部的功能缩减到了100字节多一点,真的是很费劲。迪文T5L的单片机虽然内核是51的,但是资源和频率都很充足,写个程序再也不用绞尽脑汁节省每一字节,舒坦多了。
|