完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
delay.c
#include "delay.h" static u8 fac_us=0; //us延时倍乘数 static u16 fac_ms=0; //ms延时倍乘数,在ucos下,代表每个节拍的ms数 //初始化延迟函数 //当使用OS的时候,此函数会初始化OS的时钟节拍 //SYSTICK的时钟固定为HCLK时钟的1/8 //SYSCLK:系统时钟 void delay_init() { SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8 fac_us=SystemCoreClock/8000000; //为系统时钟的1/8 fac_ms=(u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数 } //延时nus //nus为要延时的us数. 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 //对72M条件下,nms<=1864 void delay_ms(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; //清空计数器 } //延时 S //最大为18s void delay_s(u8 s) { delay_ms(s*100);//1 delay_ms(s*100);//2 delay_ms(s*100);//3 delay_ms(s*100);//4 delay_ms(s*100);//5 delay_ms(s*100);//6 delay_ms(s*100);//7 delay_ms(s*100);//8 delay_ms(s*100);//9 delay_ms(s*100);//10 } delay.h #ifndef __DELAY_H #define __DELAY_H #include "sys.h" void delay_init(void); void delay_ms(u16 nms); void delay_us(u32 nus); void delay_s(u8 s); #endif sys.c #include "sys.h" sys.h #ifndef __SYS_H #define __SYS_H #include "stm32f10x.h" //位带操作,实现51类似的GPIO控制功能 //具体实现思想,参考< //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+12) //0x4001080C #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808 #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08 #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008 #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408 #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808 #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08 #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08 //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) //输入 #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出 #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入 #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出 #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入 #endif usart.c #include "sys.h" #include "usart.h" /* 当串口不发送数据时TC标志位为0。当TC(发送完成),该位被置位为1, 表示 USART_DR内的数据已经被发送完成了。如果设置了这个位的中断, 则会产生中断。该位也有两种清零方式: 1)读 USART_SR,写USART_DR。 2)直接向该位写 0。 */ //重定向c库函数printf到串口,重定向后可使用printf函数 int fputc(int ch, FILE *f) { //发送一个字节数据到串口 USART_SendData(USART1, (uint8_t) ch);//等价于 USART1->DR = (u8) ch; //循环发送,直到发送完毕。while (0);跳出循环,while(1);代码不再向下执行 while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);//等价于while((USART1->SR&0X40)==0); return (ch); } void uart_init(u32 bound) { //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//使能USART1时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能GPIOA时钟 //USART1_TX GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9 //USART1_RX GPIOA.10初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 //USART 初始化设置 USART_InitStructure.USART_BaudRate = bound;//串口波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接收中断 USART_Cmd(USART1, ENABLE); //使能串口1 } /*RXNE(读数据寄存器非空),默认情况下也就是没有数据接收时,该寄存器值为0 当有数据被接收到时,该位会被自动置1,就可以读出来了。这时候我们要做的就 是尽快去读取USART_DR,通过读USART_DR可以将该位清零,也可以向该位写0,直接清除。*/ //一个汉字是2个字节,一个英文字母(不分大小写)是一个字节,中文标点占三个字节, 英文标点占一个字节. u8 USART_RX_BUF[USART_REC_LEN];//接收缓冲,最大USART_REC_LEN个字节. u16 USART_RX_STA=0;//接收状态标记 /* 当接收到从电脑发过来的数据,把接收到的数据保存在 USART_RX_BUF 中,同时在 接收状态寄存器(USART_RX_STA)中计数接收到的有效数据个数,当收到回车(回车的 表示由 2 个字节组成:0X0D 和 0X0A)的第一个字节 0X0D 时,计数器将不再增加,等待 0X0A 的到来,而如果 0X0A 没有来到,则认为这次接收失败,重新开始下一次接收。如 果顺利接收到 0X0A,则标记 USART_RX_STA 的第 15 位,这样完成一次接收,并等待该 位被其他程序清除,从而开始下一次的接收,而如果迟迟没有收到 0X0D,那么在接收数 据超过 USART_REC_LEN 的时候,则会丢弃前面的数据,重新接收。 ————————————————————————————————————————————————————————————————— | USART_RX_STA ————————————————————————————————————————————————————————————————— | bit15 | bit14 | bit13~0 | ————————————————————————————————————————————————————————————————— | 接收完成标志 | 接收到0x0D标志 | 接收到有效数据的个数| ————————————————————————————————————————————————————————————————— */ void USART1_IRQHandler(void) //串口1中断服务程序 { u8 ucTemp; if(USART_GetITStatus(USART1, USART_IT_RXNE)!= RESET) //如果发生了接收中断RXNE会自动置位为1 (接收到的数据必须是0x0d 0x0a结尾) { ucTemp =USART_ReceiveData(USART1);//读取接收到的数据 if((USART_RX_STA&0x8000)==0)//接收未完成(每次进入中断服务函数都要判断bit15接收完成标志位是否置位为1) { if(USART_RX_STA&0x4000)//接收到了回车符,也就是0x0D (如果bit15接收完成标志位未置位为1,就要判断是否接收到了回车符的第一个字节。USART_RX_STA是0还是1) { if(ucTemp!=0x0A)//没有接收到回车符的第二个字节0x0A(在确定接收到0x0d后要判断是否接受到了0x0a,才能确定接收正确) USART_RX_STA=0;//接收错误,重新开始 else USART_RX_STA|=0x8000;//接收完成了(或运算是用来置位的,接收到0x0d也就收到了0x0a说明接收正确接收完成,把bit15接收完成标志位置1) } else //没有接收到了回车符,也就是没有收到0x0D,中断来了继续接收数据 { if(ucTemp==0x0D)//中断来了继续接收数据,也要先判断一下是否接受到了接收到回车符的第一个字节 USART_RX_STA|=0x4000;//如果接收到回车符的第一个字节0x0D,就要将接收到回车的bit14位0x0D标志位置1 else//中断来了继续接收数据,如果还没有接收到回车符的第一个字节,就要把接收到的数据存到缓冲区USART_RX_BUF[] { USART_RX_BUF[USART_RX_STA&0X3FFF]=ucTemp;//把寄存器USART_RX_STA的bit13~0做清零处理,用来存放接收到的数据ucTemp USART_RX_STA++;//每次接收到一个新数据就要把USART_RX_STA的值加1 if(USART_RX_STA>(USART_REC_LEN-1)) USART_RX_STA=0;//接收数据错误,重新开始接收 } } } } } usart.h #ifndef __USART_H #define __USART_H #include "stdio.h" #include "sys.h" #define USART_REC_LEN 200 //定义最大接收字节数 200 extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 extern u16 USART_RX_STA; //接收状态标记 void uart_init(u32 bound); #endif |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1618 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1545 浏览 1 评论
979 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1597 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
645浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
516浏览 3评论
532浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
505浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 15:39 , Processed in 0.686763 second(s), Total 75, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号