stm32实例学习-基本操作(寄存器)

stm32实例学习
以stm32f103rc为例

  1. 系统的启动—配置系统时钟,启动运行
    startup_stm32f0x_hd.s:栈空间的设置,进入Rest_Handler函数,设置异常向量表,时钟初始化,跳转到__main执行系统的一些准备工作,跳转到main函数;

    初始化时钟后,单片机就能开始工作

void system_init(void)
{
	RCC->CR |= 1 << 16;					//HSE ON
	while(!(RCC->CR & (1 << 17)));		//Wait HSE ready
	
	RCC->CFGR &= ~(0xF << 4);			//AHB
	RCC->CFGR |= 4 << 8;				//APB1 div 2
	RCC->CFGR &= ~(7 << 11);			//APB2
	RCC->CFGR |= 7 << 18;				//PLL
	
	RCC->CFGR &= ~(1 << 17);
	RCC->CFGR |= 1 << 16;				//HSE as PLL input
	
	RCC->CR |= 1 << 24;					//PLL ON
	while(!(RCC->CR & (1 << 25)));
	
	FLASH->ACR |= 2 << 0;				//latency
	
	RCC->CFGR |= 2 << 0;
	while(((RCC->CFGR >> 2) & 0x3) != 0x02);	
}
  1. led
void led_init(void)
{
	RCC->APB2ENR = 1 << 2;	//GPIOA clock	
	GPIOA->CRH &= ~(0xF << 0);
	GPIOA->CRH |= 3 << 0;
	GPIOA->BSRR |= 1 << 8;
	
	RCC->APB2ENR = 1 << 5;	//GPIOD clock	
	GPIOD->CRL &= ~(0xF << 8);
	GPIOD->CRL |= 3 << 8;
	GPIOD->BSRR |= 1 << 2;
}
  1. 单片机进入待机状态并唤醒
void pwr_init(void)
{
	RCC->APB1ENR |= 1 << 28;	//power clock
	PWR->CSR |= 1 << 8;			//WKUP pin enable
}

/*
	set SLEEPDEEP
	set PDDS
	clear WUF
	WFI
*/
void pwr_go_to_standby(void)
{
	SCB->SCR |= 1 << 2;
	PWR->CR |= 1 << 1;
	PWR->CR |= 1 << 2;
	__WFI();
}

监测单片机的电压PVD

```c
void pwr_init(void)
{
	RCC->APB1ENR |= 1 << 28;	//power clock
	RCC->APB2ENR |= 1 << 0;
	
	PWR->CR |= 7 << 5;			//2.9V
	PWR->CR |= 1 << 4;			//enable PVD
	
	EXTI->IMR |= 1 << 16;		//interrupt
	EXTI->FTSR |= 1 << 16;
	EXTI->RTSR |= 1 << 16;
	nvic_init(PVD_IRQn, 2, 2, 2);	
}

void PVD_IRQHandler(void)
{
	if(EXTI->PR & (1 << 16))
	{
		EXTI->PR |= 1 << 16;
		GPIOD->ODR ^= 1 << 2;
	}
}
4. 延时

```c
static uint32_t usPerTicks = 9;
static volatile uint32_t system_mills = 0;
static volatile uint32_t systick_pending = 0;
static volatile uint32_t systick_stamps = 0;

void delay_init(void)
{
	SysTick->CTRL |= 1 << 1;	//en interrupt
	SysTick->CTRL &= ~(1 << 2);	//clock = system clock / 8;
	SysTick->LOAD = usPerTicks * 1000;		//ticks per ms
	SysTick->VAL= 0;
	SysTick->CTRL |= 1 << 0;	//start
}

void SysTick_Handler(void)
{
	system_mills++;
	systick_stamps = SysTick->VAL;
	systick_pending = 0;
}

uint32_t micros_isr(void)
{
	register uint32_t ticks, ms, pending;
	
	ticks = SysTick->VAL;
	if(SCB->ICSR & 0x1FF)
	{
		systick_pending = 1;
		ticks = SysTick->VAL;
	}
	
	pending = systick_pending;
	ms = system_mills;
	return ((ms + pending) * 1000 + (usPerTicks * 1000 - ticks) / usPerTicks);
}

uint32_t micros(void)
{
	register uint32_t ticks, ms;
	
	if(SysTick->CTRL & (1 << 16))
	{
		return micros_isr();
	}
	
	do
	{
		ms = system_mills;
		ticks = SysTick->VAL;
	}while((ms != system_mills) || (ticks > systick_stamps));
	
	return (ms * 1000 + (usPerTicks * 1000 - ticks) / usPerTicks);
	
}

void delay_us(uint32_t nus)
{
	uint32_t now = micros();
	while(micros() - now < nus);
}

void delay_ms(uint32_t nms)
{
	while(nms--)
	{
		delay_us(1000);
	}
}
  1. 看门狗
    独立看门狗
void iwdg_init(void)
{
	RCC->CSR |= 1 << 0;
	while(!(RCC->CSR & (1 << 1)));
	
	IWDG->KR = 0x5555;		//cancel protetion
	IWDG->PR = 4;			//prescaler
	IWDG->RLR = 625;		//load val
	IWDG->KR = 0xCCCC;		//start
	IWDG->KR = 0xAAAA;		//reload
}

void iwdg_feed(void)
{
	IWDG->KR = 0xAAAA;
}
窗口看门狗
void wwdg_init(void)
{
	RCC->APB1ENR |= 1 << 11;	//WWDG clock
	
	WWDG->CFR |= 1 << 9;		//interrupt
	WWDG->CFR |= 80;			//config window
	WWDG->CFR |= 3 << 7;
	WWDG->CR = 0x7F;
	WWDG->CR |= 1 << 7;			//start
	
	nvic_init(WWDG_IRQn, 2, 3, 2);
}

void wwdg_feed(void)
{
	WWDG->CR = 0x7F;
}

void WWDG_IRQHandler(void)
{
	WWDG->SR = 0;
	wwdg_feed();	
	GPIOD->ODR ^= 1 << 2;
}
  1. 备份寄存器
void backup_init(void)
{
	RCC->APB1ENR |= 1 << 28;	//PWR
	RCC->APB1ENR |= 1 << 27;	//BKP clock
	
	PWR->CR |= 1 << 8;			//cancel backup protection
	
	if(RCC->CSR & (1 << 27))	//power down/up
	{				
		if(BKP->DR1 != 0x55AA)
		{
			BKP->DR1 = 0x55AA;
		}
		else
		{
			GPIOD->ODR &= ~(1 << 2);
		}		
	}
}
  1. 中断
void exti_init(void)
{
	RCC->APB2ENR |= 1 << 2;		//GPIOA
	RCC->APB2ENR |= 1 << 0;		//AFIO
	
	GPIOA->CRL &= ~(0xF << 0);			//input 
	GPIOA->CRL |= 2 << 0;
	GPIOA->ODR &= ~(1 << 0);
	
	AFIO->EXTICR[0] &= ~(0xF << 0);		//gpio--exti connect
	
	EXTI->IMR |= 1 << 0;				//exti
	EXTI->RTSR |= 1 << 0;
	
	nvic_init(EXTI0_IRQn, 2, 1, 2);
	
}

void EXTI0_IRQHandler(void)
{
	if(EXTI->PR & (1 << 0))
	{
		EXTI->PR |= 1 << 0;
		GPIOD->ODR ^= 1 << 2;
	}	
}
  1. 串口的基本使用
void usart_init(uint32_t baud)
{
	uint32_t mantissa, fraction;
	
	RCC->APB2ENR |= 1 << 4;		//GPIOA
	RCC->APB1ENR |= 1 << 17;	//USART1
	
	GPIOA->CRL &= ~(0xF << 8);
	GPIOA->CRL |= 3 << 8;
	GPIOA->CRL |= 2 << 10;		//PA2
	
	GPIOA->CRL &= ~(0xF << 12);
	GPIOA->CRL |= 1 << 14;		//PA3
	
	USART2->CR1 &= ~(1 << 12);	//8x1
	USART2->CR1 &= ~(1 << 10);	//no parity
	USART2->CR1 |= 1 << 5;		//rx not empty interrupt
	USART2->CR1 |= 1 << 3;		//tx enable
	USART2->CR1 |= 1 << 2;		//rx enable
	
	USART2->CR2 &= ~(3 << 12);	//1 stop bit
	
	mantissa = 36000000 / baud / 16;
	fraction = (uint32_t)((float)36000000 / baud - mantissa);
	USART2->BRR = (mantissa << 4) | fraction;
		
	USART2->CR1 |= 1 << 13;		//enable
	
	nvic_init(USART2_IRQn, 1, 3, 2);
}

void USART2_IRQHandler(void)
{
	uint8_t tmp;
	
	if(USART2->SR & (1 << 5))
	{
		tmp = USART2->DR;
		USART2->DR = tmp;
	}
}
  1. 基本定时器的使用
void tim2_init(void)
{
	RCC->APB1ENR |= 1 << 0;		//TIM2
	
	TIM2->CR1 |= 1 << 7;		//ARR Preload
	TIM2->CR1 &= ~(1 << 4);		//count up
	TIM2->ARR = 10000 - 1;
	TIM2->PSC = 7200 - 1;
	
	TIM2->DIER |= 1 << 0;		//Update interrupt
	
	TIM2->CR1 |= 1 << 0;		//enable
	
	nvic_init(TIM2_IRQn, 1, 2, 2);
}

void TIM2_IRQHandler(void)
{
	if(TIM2->SR & (1 << 0))
	{
		TIM2->SR &= ~(1 << 0);
		GPIOD->ODR ^= 1 << 2;
	}
}
  1. RTC秒中断
void rtc_init(void)
{
	RCC->APB1ENR |= 1 << 28;	//power clock
	RCC->APB2ENR |= 1 << 27;	//backup
	
	PWR->CR |= 1 << 8;			//rtc protection
	
	RCC->BDCR |= 1 << 16;		//reset 
	RCC->BDCR &= ~(1 << 16);	//clear reset flag
	RCC->BDCR |= 1 << 0;
	while(!(RCC->BDCR & (1 << 1)));		
	RCC->BDCR |= 1 << 8;		//LSE as RTC clock
	RCC->BDCR |= 1 << 15;		//rtc clock enable
	
	while(!(RTC->CRL & (1 << 3)));	//wait RTC ready
	
	RTC->CRL |= 1 << 4;				//go to configurtation mode
	while(!(RTC->CRL & (1 << 5)));	//wait RTC oeperation OFF	
	RTC->PRLL = 0x9C39;
	while(!(RTC->CRL & (1 << 5)));	//wait RTC oeperation OFF	
	RTC->CRH |= 1 << 0;			//second interrupt
	while(!(RTC->CRL & (1 << 5)));	//wait RTC oeperation OFF	
	
	nvic_init(RTC_IRQn, 1, 1, 2);
}

void RTC_IRQHandler(void)
{
	if(RTC->CRL & (1 << 0))
	{
		RTC->CRL &= ~(1 << 0);
		while(!(RTC->CRL & (1 << 5)));	//wait RTC oeperation OFF	
		GPIOD->ODR ^= 1 << 2;
	}
}
  1. IIC
void iic_init(void)
{
	RCC->APB2ENR |=  1 << 4;	//GPIOC
	
	GPIOC->CRH &= ~(0xF << 12);
	GPIOC->CRH |= 3 << 12;
	GPIOC->CRH |= 1 << 14;		//PC11
	
	GPIOC->CRH &= ~(0xF << 16);
	GPIOC->CRH |= 3 << 16;
	GPIOC->CRH |= 1 << 18;		//PC12 Open drain
	
	GPIOC->ODR |= 1 << 11;
	GPIOC->ODR |= 1 << 12;
	
}

void iic_start(void)
{
	IIC_SDA = 1;
	IIC_SCL = 1;
	delay_us(2);
	IIC_SDA = 0;
	delay_us(2);
	IIC_SCL = 0;
}

void iic_stop(void)
{
	IIC_SDA = 0;
	IIC_SCL = 0;
	delay_us(2);
	IIC_SCL = 1;
	delay_us(2);
	IIC_SDA = 1;
}

void iic_send_byte(uint8_t byte)
{
	IIC_SCL = 0;
	for(uint8_t i = 0; i < 8; i++)
	{
		IIC_SDA = (byte >> 7) & 0x1;
		byte <<= 1;
		delay_us(2);
		IIC_SCL = 1;
		delay_us(2);
		IIC_SCL = 0;
		delay_us(2);
	}
}

uint8_t iic_recv_byte(void)
{
	uint8_t tmp;
	
	for(uint8_t i = 0; i < 8; i++)
	{
		IIC_SCL = 0;
		delay_us(2);
		IIC_SCL = 1;
		tmp <<= 1;
		if(SDA_READ == 1)
		{
			tmp += 1;
		}
		delay_us(2);		
	}
	iic_ack();
	return tmp;
}

void iic_ack(void)
{
	IIC_SCL = 0;
	IIC_SDA = 0;
	delay_us(2);
	IIC_SCL = 1;
	delay_us(2);
	IIC_SCL = 0;
}

void iic_no_ack(void)
{
	IIC_SCL = 0;
	IIC_SDA = 1;
	delay_us(2);
	IIC_SCL = 1;
	delay_us(2);
	IIC_SCL = 0;
}

uint8_t iic_wait_ack(void)
{
	uint8_t time_out;
	
	IIC_SDA = 1;
	delay_us(2);
	IIC_SCL = 1;
	delay_us(2);
	while(SDA_READ)
	{
		if(time_out++ > 250)
		{
			iic_stop();
			return 1;
		}
	}
	IIC_SCL = 0;
	return 0;
}

  1. SPI
void spi_init(void)
{
	RCC->APB2ENR |= 1 << 2;
	RCC->APB2ENR |= 1 << 12;
	
	GPIOA->CRL &= ~(0xF << 20);
	GPIOA->CRL |= 3 << 20;		//SCK
	GPIOA->CRL |= 2 << 22;
	GPIOA->CRL &= ~(0xF << 24);
	GPIOA->CRL |= 2 << 26;
	GPIOA->ODR |= 1 << 6;		//MISO input 
	GPIOA->CRL |= ~((uint32_t)0xF << 28);
	GPIOA->CRL |= (uint32_t)2 << 30;
	GPIOA->CRL |= (uint32_t)3 << 28;		//MOSI	output
	
	SPI1->CR1 |= 1 << 15;		//bidirection
	SPI1->CR1 &= ~(1 << 11);	//8bit
	SPI1->CR1 |= 1 << 9;		//soft 
	SPI1->CR1 |= 1 << 8;		//SSI
	SPI1->CR1 &= ~(1 << 7);		//MSB
	SPI1->CR1 |= 2 << 3;		//BAUD
	SPI1->CR1 |= 1 << 2;		//Master
	SPI1->CR1 &= ~(1 << 1);		//CPOL low
	SPI1->CR1 &= ~(1 << 0);		//CPHA low	
	
	SPI1->CR1 |= 1 << 6;		//enable
	
}

uint8_t spi_write_read_byte(uint8_t byte)
{
	while(!(SPI1->SR & (1 << 1)))
	{
		
	}
	SPI1->DR = byte;
	
	while(!(SPI1->SR & (1 << 0)))
	{
		
	}
	return SPI1->DR;
}
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值