-
- //位带操作,实现51类似的GPIO控制功能
- //具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).M4同M3类似,只是寄存器地址变了.
- //IO口操作宏定义
- #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
- #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
- #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
- //IO口地址映射
- #define GPIOA_ODR_Addr (GPIOA_BASE+20) //0x40020014
- #define GPIOB_ODR_Addr (GPIOB_BASE+20) //0x40020414
- #define GPIOC_ODR_Addr (GPIOC_BASE+20) //0x40020814
- #define GPIOD_ODR_Addr (GPIOD_BASE+20) //0x40020C14
- #define GPIOE_ODR_Addr (GPIOE_BASE+20) //0x40021014
- #define GPIOF_ODR_Addr (GPIOF_BASE+20) //0x40021414
- #define GPIOG_ODR_Addr (GPIOG_BASE+20) //0x40021814
- #define GPIOH_ODR_Addr (GPIOH_BASE+20) //0x40021C14
- #define GPIOI_ODR_Addr (GPIOI_BASE+20) //0x40022014
- #define GPIOA_IDR_Addr (GPIOA_BASE+16) //0x40020010
- #define GPIOB_IDR_Addr (GPIOB_BASE+16) //0x40020410
- #define GPIOC_IDR_Addr (GPIOC_BASE+16) //0x40020810
- #define GPIOD_IDR_Addr (GPIOD_BASE+16) //0x40020C10
- #define GPIOE_IDR_Addr (GPIOE_BASE+16) //0x40021010
- #define GPIOF_IDR_Addr (GPIOF_BASE+16) //0x40021410
- #define GPIOG_IDR_Addr (GPIOG_BASE+16) //0x40021810
- #define GPIOH_IDR_Addr (GPIOH_BASE+16) //0x40021C10
- #define GPIOI_IDR_Addr (GPIOI_BASE+16) //0x40022010
-
- //IO口操作,只对单一的IO口!
- //确保n的值小于16!
- #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
- #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
- #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
- #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
- #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
- #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入
- #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
- #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
- #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
- #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
delay.c的一些延时函数:
- void delay_us(u32 nus)
- {
- u32 temp;
- SysTick->LOAD=nus*fac_us; //时间加载
- SysTick->VAL=0x00; //清空计数器
- SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
- do
- {
- temp=SysTick->CTRL;
- }while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
- SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
- SysTick->VAL =0X00; //清空计数器
- }
- //延时nms
- //注意nms的范围
- //SysTick->LOAD为24位寄存器,所以,最大延时为:
- //nms<=0xffffff*8*1000/SYSCLK
- //SYSCLK单位为Hz,nms单位为ms
- //对168M条件下,nms<=798ms
- void delay_xms(u16 nms)
- {
- u32 temp;
- SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit)
- SysTick->VAL =0x00; //清空计数器
- SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
- do
- {
- temp=SysTick->CTRL;
- }while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
- SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
- SysTick->VAL =0X00; //清空计数器
- }
- //延时nms
- //nms:0~65535
- void delay_ms(u16 nms)
- {
- u8 repeat=nms/540; //这里用540,是考虑到某些客户可能超频使用,
- //比如超频到248M的时候,delay_xms最大只能延时541ms左右了
- u16 remain=nms%540;
- while(repeat)
- {
- delay_xms(540);
- repeat--;
- }
- if(remain)delay_xms(remain);
- }
debug_usart.c里面设定为调试串口的配置:
- //加入以下代码,支持printf函数,而不需要选择use MicroLIB
- #if 1
- #pragma import(__use_no_semihosting)
- //标准库需要的支持函数
- struct __FILE
- {
- int handle;
- };
- FILE __stdout;
- //定义_sys_exit()以避免使用半主机模式
- void _sys_exit(int x)
- {
- x = x;
- }
- //重定义fputc函数
- int fputc(int ch, FILE *f)
- {
- USART_SendData(DBG_USARTx, (uint8_t)ch);
- /* Loop until the end of transmission */
- while (USART_GetFlagStatus(DBG_USARTx, USART_FLAG_TXC) == RESET)
- {
- }
-
- return ch;
- }
- #endif
- #if EN_DBG_USART_RX //如果使能了接收
- //串口1中断服务程序
- //注意,读取USARTx->SR能避免莫名其妙的错误
- u8 DBG_USART_RX_BUF[DBG_USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
- //接收状态
- //bit15, 接收完成标志
- //bit14, 接收到0x0d
- //bit13~0, 接收到的有效字节数目
- u16 DBG_USART_RX_STA=0; //接收状态标记
- #endif
- void DBG_UART_Init(u32 bound)
- {
- GPIO_InitType GPIO_InitStructure;
- USART_InitType USART_InitStructure;
-
- #if EN_DBG_USART_RX
- NVIC_InitType NVIC_InitStructure;
- #endif
-
- //GPIO初始化
- GPIO_InitStruct(&GPIO_InitStructure);
-
- DBG_PERIPH_GPIO_APBxClkCmd(DBG_PERIPH_GPIO_AF | DBG_PERIPH_GPIO, ENABLE);
- DBG_PERIPH_APBxClkCmd(DBG_PERIPH, ENABLE);
- GPIO_InitStructure.Pin = DBG_TX_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Slew_Rate = GPIO_Slew_Rate_High;
- GPIO_InitStructure.GPIO_Alternate = DBG_TX_GPIO_AF;
- GPIO_InitPeripheral(DBG_GPIO, &GPIO_InitStructure);
- GPIO_InitStructure.Pin = DBG_RX_PIN;
- GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Alternate = DBG_RX_GPIO_AF;
- GPIO_InitPeripheral(DBG_GPIO, &GPIO_InitStructure);
-
- #if EN_DBG_USART_RX
- //中断优先级配置
- /* Configure the NVIC Preemption Priority Bits */
- //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//在main函数里面统一配置
- /* Enable the USARTy Interrupt */
- NVIC_InitStructure.NVIC_IRQChannel = DBG_USART_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- #endif
- //串口配置
- USART_InitStructure.BaudRate = bound;
- USART_InitStructure.WordLength = USART_WL_8B;
- USART_InitStructure.StopBits = USART_STPB_1;
- USART_InitStructure.Parity = USART_PE_NO;
- USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
- USART_InitStructure.Mode = USART_MODE_RX |USART_MODE_TX;
- // init uart
- USART_Init(DBG_USARTx, &USART_InitStructure);
- #if EN_DBG_USART_RX //发送中断默认不开启
- /* Enable USARTy Receive and Transmit interrupts */
- USART_ConfigInt(DBG_USARTx, USART_INT_RXDNE, ENABLE);
- //USART_ConfigInt(DBG_USARTx, USART_INT_TXDE, ENABLE);
- #endif
- // enable uart
- USART_Enable(DBG_USARTx, ENABLE);
- }
- #if EN_DBG_USART_RX
- void DBG_USART_IRQHandler(void) //串口1中断服务程序
- {
- u8 Res;
- #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
- OSIntEnter();
- #endif
- if(USART_GetIntStatus(DBG_USARTx, USART_INT_RXDNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
- {
- Res =USART_ReceiveData(DBG_USARTx);//(USART1->DR); //读取接收到的数据
-
- if((DBG_USART_RX_STA&0x8000)==0)//接收未完成
- {
- if(DBG_USART_RX_STA&0x4000)//接收到了0x0d
- {
- if(Res!=0x0a)DBG_USART_RX_STA=0;//接收错误,重新开始
- else DBG_USART_RX_STA|=0x8000; //接收完成了
- }
- else //还没收到0X0D
- {
- if(Res==0x0d)DBG_USART_RX_STA|=0x4000;
- else
- {
- DBG_USART_RX_BUF[DBG_USART_RX_STA&0X3FFF]=Res ;
- DBG_USART_RX_STA++;
- if(DBG_USART_RX_STA>(DBG_USART_REC_LEN-1))DBG_USART_RX_STA=0;//接收数据错误,重新开始接收
- }
- }
- }
- }
- #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
- OSIntExit();
- #endif
- }
- #endif
除了3个核心文件外,还写了LED的配置:
- #ifndef __LED_NEW_H_
- #define __LED_NEW_H_
- #include "sys.h"
- //LED端口定义
- #define LED1 PAout(8) // D1
- #define LED2 PBout(4) // D2
- #define LED3 PBout(5) // D3
- void LED_Init(void);
- #endif
- void LED_Init(void)
- {
- GPIO_InitType GPIO_InitStructure;
- RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA|RCC_APB2_PERIPH_GPIOB, ENABLE);
- /* Configure the GPIO pin */
- GPIO_InitStruct(&GPIO_InitStructure);
- //PA8
- GPIO_InitStructure.Pin = GPIO_PIN_8;
- GPIO_InitStructure.GPIO_Current = GPIO_DC_4mA;
- GPIO_InitStructure.GPIO_Pull = GPIO_No_Pull;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
- //PB4 PB5
- GPIO_InitStructure.Pin = GPIO_PIN_4|GPIO_PIN_5;
- GPIO_InitStructure.GPIO_Current = GPIO_DC_4mA;
- GPIO_InitStructure.GPIO_Pull = GPIO_No_Pull;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
-
- //默认LED关闭状态
- LED1=0;
- LED2=0;
- LED3=0;
- }
最终我们设定一个任务:将输入的字符,重新输出,并让一个LED闪烁~
- int main(void)
- {
- u8 t;
- u8 len;
- u16 times=0;
- /*SystemInit() function has been called by startup file startup_n32g43x.s*/
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
- delay_init(108); //延时初始化
- DBG_UART_Init(115200); //串口初始化波特率为115200
- LED_Init(); //初始化与LED连接的硬件接口
- while(1)
- {
- if(DBG_USART_RX_STA&0x8000)
- {
- len=DBG_USART_RX_STA&0x3fff;//得到此次接收到的数据长度
- printf("\r\n您发送的消息为:\r\n");
- for(t=0;t<len;t++)
- {
- USART_SendData(DBG_USARTx, DBG_USART_RX_BUF[t]); //向串口1发送数据
- while (USART_GetFlagStatus(DBG_USARTx, USART_FLAG_TXC) == RESET);//等待发送结束
- }
- printf("\r\n\r\n");//插入换行
- DBG_USART_RX_STA=0;
- }else
- {
- times++;
- if(times%5000==0)
- {
- printf("\r\nN32G435CL-DEMOBOARD 串口实验\r\n");
- printf("JasonQiu@21ic\r\n\r\n\r\n");
- }
- if(times%200==0)printf("请输入数据,以回车键结束\r\n");
- if(times%30==0)LED1=!LED1;//闪烁LED,提示系统正在运行.
- delay_ms(10);
- }
- }
- }
编译无误后,我们下载,查看串口,我们发送什么,它就会回发回来,且LED闪烁:
好了,开箱及DEMO程序就到这了,谢谢大家观看~