底层函数编写(gpio,uart)
写这篇博客算是自我激励吧,一直以来都没有说有特别大的决心去做一件事,想通过这种方式去让自己有所坚持,有所进步吧。我也觉得面对一件事,要么就不要开始,要么就尽己所能去做好。
gpio.h
#ifndef GPIO_H
#define GPIO_H
typedef struct
{
uint32 PDOR ; //端口数据输出寄存器
uint32 PSOR ; //端口数据置一寄存器
uint32 PCOR ; //端口数据清零寄存器
uint32 PTOR ; //端口数据反转寄存器
uint32 PDIR ; //端口数据输入寄存器
uint32 PDDR ; //端口数据方向寄存器
}volatile *GPIO_MemMapPtr;
typedef struct PORT_MemMap
{
uint32 PCR[32]; //32个引脚
uint32 GPCLR;
uint32 GPCHR;
uint8 RESERVED_0[24];
uint32 ISFR; //中断配置寄存器
}volatile *PORT_MemMapPtr;
//这里首先定义了两个结构体变量,一个是port register,一个是gpio register,印象特别深的是关于两者的差别,我的理解是port register 初始化通用的一些端口设置,gpio register用于初始化gpio的一些设置,比如说中断必须在port里面设置。
//这里的GPIO_Type *是和GPIO_MemMapPtr等价的
#define PTA ((GPIO_Type *)PTA_BASE)
/** Peripheral PTB base address */
#define PTB_BASE (0x400FF040u)
/** Peripheral PTB base pointer */
#define PTB ((GPIO_Type *)PTB_BASE)
/** Peripheral PTC base address */
#define PTC_BASE (0x400FF080u)
/** Peripheral PTC base pointer */
#define PTC ((GPIO_Type *)PTC_BASE)
/** Peripheral PTD base address */
#define PTD_BASE (0x400FF0C0u)
/** Peripheral PTD base pointer */
#define PTD ((GPIO_Type *)PTD_BASE)
/** Peripheral PTE base address */
#define PTE_BASE (0x400FF100u)
/** Peripheral PTE base pointer */
#define PTE ((GPIO_Type *)PTE_BASE)
#define g_PORTA_BASE_PTR ((PORT_MemMapPtr)0x40049000u)
#define g_PORTB_BASE_PTR ((PORT_MemMapPtr)0x4004A000u)
#define g_PORTC_BASE_PTR ((PORT_MemMapPtr)0x4004B000u)
#define g_PORTD_BASE_PTR ((PORT_MemMapPtr)0x4004C000u)
#define g_PORTE_BASE_PTR ((PORT_MemMapPtr)0x4004D000u)
#define g_PTA_BASE_PTR ((GPIO_MemMapPtr)0x40049000u)
#define g_PTB_BASE_PTR ((GPIO_MemMapPtr)0x4004A000u)
#define g_PTC_BASE_PTR ((GPIO_MemMapPtr)0x4004B000u)
#define g_PTD_BASE_PTR ((GPIO_MemMapPtr)0x4004C000u)
#define g_PTE_BASE_PTR ((GPIO_MemMapPtr)0x4004D000u)
#define g_GPIO_PDOR_REG(base) ((base)->PDOR)
#define g_GPIO_PSOR_REG(base) ((base)->PSOR)
#define g_GPIO_PCOR_REG(base) ((base)->PCOR)
#define g_GPIO_PTOR_REG(base) ((base)->PTOR)
#define g_GPIO_PDIR_REG(base) ((base)->PDIR)
#define g_GPIO_PDDR_REG(base) ((base)->PDDR)
#define g_PORT_PCR_REG(port_ptr,port_bit) ((port_ptr)->PCR[port_bit])
#define g_PORT_ISFR_REG(base) ((base)->ISFR)
#define OUTPUT_L 0
#define OUTPUT_H 1
#define INPUT_PULL_DOWN (0|PORT_PCR_PE_MASK)
#define INPUT_PULL_UP (PORT_PCR_PS_MASK|PORT_PCR_PE_MASK)
#define PORT_PCR_MUX(x) (((uint32_t)(((uint32_t)(x))<<PORT_PCR_MUX_SHIFT))&PORT_PCR_MUX_MASK)
//typedef void (*GPIO_ISR_CALLBACK)(void);
//GPIO_ISR_CALLBACK GPIO_ISR[5];
uint8 g_LPLD_GPIO_Init(GPIO_Type * port ,uint8 pin,uint8 dir ,uint8 data);
void g_LPLD_GPIO_Set(GPIO_Type *port,uint8 pin,uint8 data);
uint32 g_LPLD_GPIO_Get(GPIO_Type *port,uint8 pin);
PORT_MemMapPtr ptToPort(GPIO_Type * port);
void delay_ms(long int time);
void gpio_turn (GPIO_Type * port,uint8 pin);
typedef void (*GPIO_ISR_CALLBACK)(void);
void port_isr(void);
#endif
对于头文件的梗,最想说的是关于拉普兰德v3库很多变量都变了,然后补各种变量,函数。但慢慢的写底层也看到的一些函数了解到了一些单片机原理,关于寄存器, 最直接的感受便是通过定位改变相应位的数值实现对零件的控制。
gpio.c
#include "common.h"
#include "gpio.h"
PORT_MemMapPtr ptToPort(GPIO_Type * port)
{
if(port==PTA)
return g_PORTA_BASE_PTR;
else if(port==PTB)
return g_PORTB_BASE_PTR;
else if(port==PTC)
return g_PORTC_BASE_PTR;
else if(port==PTD)
return g_PORTD_BASE_PTR;
else if(port==PTE)
return g_PORTE_BASE_PTR;
else
return 0;
}
uint8 g_LPLD_GPIO_Init(GPIO_Type *port,uint8 pin,uint8 dir ,uint8 data)
{
GPIO_Type *gpio_ptr=port;
PORT_MemMapPtr port_ptr=ptToPort(port);
ASSERT(port<PTE);
ASSERT(pin<=31);
ASSERT(dir<=1);
ASSERT(data<=1);
g_PORT_PCR_REG(port_ptr,pin)=PORT_PCR_MUX(1); //设置端口复用
GPIO_ISR_CALLBACK isr_func = port_isr; //关于这里首先是指定了中断函数
enable_irq((IRQn_Type)(0 + PORTA_IRQn)); //接着是启用中断函数
if(dir==DIR_OUTPUT)
{
g_GPIO_PDDR_REG(gpio_ptr)|=0x1u<<pin;
if(data==OUTPUT_H)
g_GPIO_PSOR_REG(gpio_ptr)=0x1u<<pin;
else
g_GPIO_PCOR_REG(gpio_ptr)=0x1u<<pin;
}
else
{
g_GPIO_PDDR_REG(gpio_ptr)&=~(0x1u<<pin);
if(data==INPUT_PULL_UP)
g_PORT_PCR_REG(port_ptr,pin)|=PORT_PCR_PE_MASK|PORT_PCR_PS_MASK;
else if(data==INPUT_PULL_DOWN)
g_PORT_PCR_REG(port_ptr,pin)=PORT_PCR_PE_MASK;
else
g_PORT_PCR_REG(port_ptr,pin)&=~PORT_PCR_PE_MASK;
}
//这里其实也可以通过移位&实现对应位置设置
return 1;
}
void g_LPLD_GPIO_Set(GPIO_Type * port,uint8 pin,uint8 data)
{
GPIO_Type *gpio_ptr=port;
gpio_ptr->PDOR = (gpio_ptr->PDOR & ~(0x01L<<pin)) | (uint32)(data << pin);
}
uint32 g_LPLD_GPIO_Get(GPIO_Type * port,uint8 pin)
{
GPIO_Type *gpio_ptr=port;
return gpio_ptr->PDIR>=1?1:0;
}
//一个简易的延时函数
void delay_ms(long int time)
{
int i,j;
for (i = 0; i<1000; i++)
for(j = 0; j < 1000; j++);
}
void gpio_turn (GPIO_Type * port,uint8 pin)
{
GPIO_Type *gpio_ptr=port;
gpio_ptr->PTOR |= (1 << pin);
}
void port_isr(void)
{
if(LPLD_GPIO_IsPinxExt(PORTA, GPIO_Pin19))
{
//去抖
delay_ms(10);
if(PTA19_I==0)
{
PTA10_O=0;
delay_ms(10);delay_ms(10);delay_ms(10);
delay_ms(10);delay_ms(10);delay_ms(10);
delay_ms(10);delay_ms(10);delay_ms(10);
}
else
{
PTA10_O=0;
delay_ms(10);delay_ms(10);delay_ms(10);
delay_ms(10);delay_ms(10);delay_ms(10);
delay_ms(10);delay_ms(10);delay_ms(10);
}
}
}
uart.h
#ifndef UART_H
#define UART_H
typedef struct g_UART_MemMapPtr
{
uint8 BDH; /**< UART Baud Rate Registers:High, offset: 0x0 */
uint8 BDL; /**< UART Baud Rate Registers: Low, offset: 0x1 */
uint8 C1; /**< UART Control Register 1, offset: 0x2 */
uint8 C2; /**< UART Control Register 2, offset: 0x3 */
uint8 S1; /**< UART Status Register 1, offset: 0x4 */
uint8 S2; /**< UART Status Register 2, offset: 0x5 */
uint8 C3; /**< UART Control Register 3, offset: 0x6 */
uint8 D; /**< UART Data Register, offset: 0x7 */
uint8 MA1; /**< UART Match Address Registers 1, offset: 0x8 */
uint8 MA2; /**< UART Match Address Registers 2, offset: 0x9 */
uint8 C4; /**< UART Control Register 4, offset: 0xA */
uint8 C5; /**< UART Control Register 5, offset: 0xB */
uint8 ED; /**< UART Extended Data Register, offset: 0xC */
uint8 MODEM; /**< UART Modem Register, offset: 0xD */
uint8 IR; /**< UART Infrared Register, offset: 0xE */
uint8 RESERVED_0[1];
uint8 PFIFO; /**< UART FIFO Parameters, offset: 0x10 */
uint8 CFIFO; /**< UART FIFO Control Register, offset: 0x11 */
uint8 SFIFO; /**< UART FIFO Status Register, offset: 0x12 */
uint8 TWFIFO; /**< UART FIFO Transmit Watermark, offset: 0x13 */
uint8 TCFIFO; /**< UART FIFO Transmit Count, offset: 0x14 */
uint8 RWFIFO; /**< UART FIFO Receive Watermark, offset: 0x15 */
uint8 RCFIFO; /**< UART FIFO Receive Count, offset: 0x16 */
uint8 RESERVED_1[1];
uint8 C7816; /**< UART 7816 Control Register, offset: 0x18 */
uint8 IE7816; /**< UART 7816 Interrupt Enable Register, offset: 0x19 */
uint8 IS7816; /**< UART 7816 Interrupt Status Register, offset: 0x1A */
union
{ /* offset: 0x1B */
uint8 WP7816_T_TYPE0; /**< UART 7816 Wait Parameter Register, offset: 0x1B */
uint8 WP7816_T_TYPE1; /**< UART 7816 Wait Parameter Register, offset: 0x1B */
};
uint8 WN7816; /**< UART 7816 Wait N Register, offset: 0x1C */
uint8 WF7816; /**< UART 7816 Wait FD Register, offset: 0x1D */
uint8 ET7816; /**< UART 7816 Error Threshold Register, offset: 0x1E */
uint8 TL7816;
}volatile *g_UART_MemMapPtr;
#ifndef UART0_BASE
#define UART0_BASE (0x4006A000u)
/** Peripheral UART0 base pointer */
#define UART0 ((g_UART_MemMapPtr)UART0_BASE)
/** Peripheral UART1 base address */
#define UART1_BASE (0x4006B000u)
/** Peripheral UART1 base pointer */
#define UART1 ((g_UART_MemMapPtr)UART1_BASE)
/** Peripheral UART2 base address */
#define UART2_BASE (0x4006C000u)
/** Peripheral UART2 base pointer */
#define UART2 ((g_UART_MemMapPtr)UART2_BASE)
/** Peripheral UART3 base address */
#define UART3_BASE (0x4006D000u)
/** Peripheral UART3 base pointer */
#define UART3 ((g_UART_MemMapPtr)UART3_BASE)
/** Peripheral UART4 base address */
#define UART4_BASE (0x400EA000u)
/** Peripheral UART4 base pointer */
#define UART4 ((g_UART_MemMapPtr)UART4_BASE)
/** Peripheral UART5 base address */
#define UART5_BASE (0x400EB000u)
/** Peripheral UART5 base pointer */
#define UART5 ((g_UART_MemMapPtr)UART5_BASE)
#endif
typedef enum UARTn
{
g_UART0=UART0_BASE,
g_UART1=UART1_BASE,
g_UART2=UART2_BASE,
g_UART3=UART3_BASE,
g_UART4=UART4_BASE,
g_UART5=UART5_BASE,
}UARTn;
typedef struct SIM_Type
{
uint32 SOPT1; /**< System Options Register 1, offset: 0x0 */
uint8 RESERVED_0[4096];
uint32 SOPT2; /**< System Options Register 2, offset: 0x1004 */
uint8 RESERVED_1[4];
uint32 SOPT4; /**< System Options Register 4, offset: 0x100C */
uint32 SOPT5; /**< System Options Register 5, offset: 0x1010 */
uint32 SOPT6; /**< System Options Register 6, offset: 0x1014 */
uint32 SOPT7; /**< System Options Register 7, offset: 0x1018 */
uint8 RESERVED_2[8];
uint32 SDID; /**< System Device Identification Register, offset: 0x1024 */
uint32 SCGC1; /**< System Clock Gating Control Register 1, offset: 0x1028 */
uint32 SCGC2; /**< System Clock Gating Control Register 2, offset: 0x102C */
uint32 SCGC3; /**< System Clock Gating Control Register 3, offset: 0x1030 */
uint32 SCGC4; /**< System Clock Gating Control Register 4, offset: 0x1034 */
uint32 SCGC5; /**< System Clock Gating Control Register 5, offset: 0x1038 */
uint32 SCGC6; /**< System Clock Gating Control Register 6, offset: 0x103C */
uint32 SCGC7; /**< System Clock Gating Control Register 7, offset: 0x1040 */
uint32 CLKDIV1; /**< System Clock Divider Register 1, offset: 0x1044 */
uint32 CLKDIV2; /**< System Clock Divider Register 2, offset: 0x1048 */
uint32 FCFG1; /**< Flash Configuration Register 1, offset: 0x104C */
uint32 FCFG2; /**< Flash Configuration Register 2, offset: 0x1050 */
uint32 UIDH; /**< Unique Identification Register High, offset: 0x1054 */
uint32 UIDMH; /**< Unique Identification Register Mid-High, offset: 0x1058 */
uint32 UIDML; /**< Unique Identification Register Mid Low, offset: 0x105C */
uint32 UIDL; /**< Unique Identification Register Low, offset: 0x1060 */
} volatile *g_SIM_Type;
#define SIM_BASE (0x40047000u)
#define SIM ((SIM_Type *)SIM_BASE)
#define SIM_SCGC4_REG(base) ((base)->SCG4)
uint32 SCGC4;
#define SIM_SCGC4 SIM_SCGC4_REG(SIM_BASE_PTR)
#define UART_C2_REG(base) ((base)->C2)
#define UART_C1_REG(base) ((base)->C1)
#define UART_BDH_REG(base) ((base)->BDH)
#define UART_BDL_REG(base) ((base)->BDL)
#define UART_C4_REG(base) ((base)->C4)
#define UART_D_REG(base) ((base)->D)
#define UART_PFIFO_REG(base) ((base)->PFIFO)
void uart_init(UARTn uartn,uint32 baud,uint32 PORT_TX,uint32 PORT_RX);
void uart_send1(UARTn uartn,uint8 ch);
void uart_sendn(UARTn uarrtn,uint16 len,uint8 *buff);
void uart_re1(UARTn uartn,uint8 fp);
void uart_ren(UARTn uarrtn,uint16 len,uint8 *buff);
void uart_enable_re_init(UARTn uartn);
void uart_disable_re_init(UARTn uartn);
#endif
uart.c
#include "common.h"
#include "uart.h"
void uart_init(UARTn uartn,uint32 baud,uint32 PORT_TX,uint32 PORT_RX)
{
register uint16 sbr,brfa;
uint8 temp;
uint32 sysclk;
switch(uartn)
{
case g_UART0:
SCGC4|=SIM_SCGC4_UART0_MASK;
if(PORT_TX==PTA1)
PORTA->PCR[2] = PORT_PCR_MUX(2);
else if(PORT_TX == PTA2)
PORTA->PCR[2] = PORT_PCR_MUX(2);
else if(PORT_TX == PTA14)
PORTA->PCR[14] = PORT_PCR_MUX(3);
else
PORTB->PCR[17] = PORT_PCR_MUX(3);
if(PORT_RX == PTA1)
PORTA->PCR[1] = PORT_PCR_MUX(2);
else if(PORT_RX == PTA15)
PORTA->PCR[15] = PORT_PCR_MUX(3);
else
PORTB->PCR[16] = PORT_PCR_MUX(3);
UART_C2_REG((g_UART_MemMapPtr)uartn)&=~(0|UART_C2_TE_MASK|UART_C2_RE_MASK);
UART_C1_REG((g_UART_MemMapPtr)uartn)|=(0|UART_C1_PE_MASK|UART_C1_PT_MASK);
if((uartn==g_UART0)||(uartn==g_UART1))
{
sysclk=g_core_clock*1000;
}
else
{
sysclk=g_core_clock*1000;
}
sbr=(uint16)(sysclk/(baud*16));
if(sbr>0x1FFF)
sbr=0x1FFF;
brfa=(sysclk/baud)-(sbr*16);
temp=UART_BDH_REG((g_UART_MemMapPtr)uartn)&(~UART_BDH_SBR_MASK);
UART_BDH_REG((g_UART_MemMapPtr)uartn)=temp|UART_BDH_SBR(sbr>>8);
UART_BDL_REG((g_UART_MemMapPtr)uartn)=UART_BDL_SBR(sbr);
temp=UART_C4_REG((g_UART_MemMapPtr)uartn)&(~UART_C4_BRFA_MASK);
UART_C4_REG((g_UART_MemMapPtr)uartn)=temp|UART_C4_BRFA(brfa);
UART_PFIFO_REG((g_UART_MemMapPtr)uartn)|=(0|UART_PFIFO_TXFE_MASK|UART_PFIFO_RXFE_MASK);
UART_C2_REG((g_UART_MemMapPtr)uartn)|=(0|UART_C2_TE_MASK|UART_C2_RE_MASK);
}
}
void uart_send1(UARTn uartn,uint8 ch)
{
while(!(((g_UART_MemMapPtr)uartn)->S1&UART_S1_TDRE_MASK));
UART_D_REG((g_UART_MemMapPtr)uartn)=ch;
}
void uart_sendn(UARTn uartn,uint16 len,uint8 *buff)
{
for(int n=0;n<len;n++)
{
uart_send1(uartn,*(buff++));
}
}
void uart_re1(UARTn uartn,uint8 fp)
{
while(!(((g_UART_MemMapPtr)uartn)->S1)&UART_S1_RDRF_MASK);
fp=(((g_UART_MemMapPtr)uartn)->D);
void uart_enable_re_init(UARTn uartn)
{
(((g_UART_MemMapPtr)uartn)->C2)|=UART_C2_TIE_MASK;
if(uartn == g_UART2)
enable_irq((int) (( ( (UART0_BASE/*(uint32)uartn*/)>>12 )&0x0000000Fu ) - 0x0000000A + (uint32)UART0_RX_TX_IRQn));
}
void uart_disable_re_init(UARTn uartn)
{
UART_C2_REG((g_UART_MemMapPtr)uartn)&=~UART_C2_TIE_MASK;
if(!(UART_C2_REG((g_UART_MemMapPtr)uartn))&(UART_C2_TIE_MASK|UART_C2_TCIE_MASK))
disable_irq((int) (( ( (UART0_BASE/*(uint32)uartn*/)>>12 )&0x0000000Fu ) - 0x0000000A + (uint32)UART0_RX_TX_IRQn));
}
main.c
#include "common.h"
#include "gpio.h"
enum LEDn
{
LEDG=10,
LEDR=11,
LEDB=12,
};
enum led_status
{
led_on=1,
led_down=0,
};
void main (void)
{
//printf("hello world");
g_LPLD_GPIO_Init(PTA ,LEDG ,DIR_OUTPUT ,1);
g_LPLD_GPIO_Init(PTA ,LEDR ,DIR_OUTPUT ,1);
g_LPLD_GPIO_Init(PTA ,LEDB ,DIR_OUTPUT ,1);
while(1)
{
delay_ms(50);
g_LPLD_GPIO_Set(PTA ,LEDB ,0);
delay_ms(50);
g_LPLD_GPIO_Set(PTA ,LEDB ,1);
delay_ms(50);
g_LPLD_GPIO_Set(PTA ,LEDG ,0);
delay_ms(50);
g_LPLD_GPIO_Set(PTA ,LEDG ,1);
delay_ms(50);
g_LPLD_GPIO_Set(PTA ,LEDR ,0);
delay_ms(50);
g_LPLD_GPIO_Set(PTA ,LEDR ,1);
}
}
总结:上面的很多都是自己敲的,最后都最后实现流水灯真的很不易,很多bug都是学长帮助改的,但当真正的实现一些功能,还是觉得很值的。希望接下来自己能更加的努力,争取能够完成十二月份的校内赛。