stm32迁移
stm32迁移
首先从C51 迁移到 == stm32== 会有部分代码不一样,主要就是stm32所有的初始状态需要自己初始化
位带
位带方便易于迁移,因为stm32没有sbit定义的方式
位带初始化函数,主要用于IO口
#ifndef _system_H
#define _system_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
SysTick定时寄存器 4种
CTRL寄存器
- 0 使能 1
- 1 常用0 也就是倒计时为0的时候如果有中断或者特殊的请求 就是1,反之就是0
- 2 常用0
- 16 循环判断如果为1代表已经倒计时到0了
LOAD寄存器 (用来重载重新计数的,也就是装弹)
LOAD 是 SysTick 定时器的重装载数值寄存器
VAL寄存器 (用来存储计数的)
VAL 是 SysTick 定时器的当前数值寄存器
CALIB寄存器
CALIB 是 SysTick 定时器的校准数值寄存器
此寄存器在定时实验中不需要使用,可以不用了解。
操作步骤
SysTick 定时器的操作可以分为 4 步:
(1)设置 SysTick 定时器的时钟源。
(2)设置 SysTick 定时器的重装初始值(如果要使用中断的话,就将中断使能打开)。
(3)清零 SysTick 定时器当前计数器的值。
(4)打开 SysTick 定时器
#include "public.h"
void SysTick_Init(u8 SYSCLK)//SYSCLK:系统时钟频率
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //设置系统时钟源为HCLK/8 系统时钟8分频
}
void delay_us(u32 nus)
{
u32 u32temp=0;
SysTick->LOAD=nus*9; //设置计数器的值为nus*9 9M的频率每执行9次为1us
SysTick->VAL=0; //清空计数器CURRENT
SysTick->CTRL|=1; //开启计数器 就是第一位为1使能
do{
u32temp=SysTick->CTRL; //读取计数器当前值
//!(u32temp&(1<<16)) 数值一直减减 不为1证明倒计时没结束 u32temp&0x01时钟使能
}while(!(u32temp&(1<<16))&&(u32temp&0x01)); //死循环等待计数器到达0
//时钟失能 也就是第一个比特为0
SysTick->CTRL&=~1; //关闭计数器
SysTick->VAL=0; //清空计数器CURRENT
}
void delay_ms(u16 nms)
{
u32 u32temp=0;
if(nms>1860) nms=1860; //最大延时1860ms
SysTick->LOAD=nms*9000; //设置计数器的值为nms*9000
SysTick->VAL=0; //清空计数器CURRENT
SysTick->CTRL|=1; //开启计数器
do{
u32temp=SysTick->CTRL; //读取计数器当前值
}while(!(u32temp&(1<<16))&&(u32temp&0x01)); //死循环等待计数器到达0
SysTick->CTRL&=~1; //关闭计数器
SysTick->VAL=0; //清空计数器CURRENT
}
迁移过程
初始化
初始化都需要一个初始化系统时钟,否则就会不出现效果
所以这个时候main就需要初始化一个计时器
int main()
{
SysTick_Init(72);
}
.h的初始化
//定义引脚
#define LED_PORT GPIOA //定义GPIO的组
#define LED_PIN GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7 //定义GPIO的引脚号可以或起来
#define LED_PORT_RCC RCC_APB2Periph_GPIOA //定义GPIO的时钟总线
#define RCLK_PORT GPIOB
#define RCLK_PIN GPIO_Pin_5
#define RCLK_PORT_RCC RCC_APB2Periph_GPIOB
#define SER_PORT GPIOB
#define SER_PIN GPIO_Pin_4
#define SER_PORT_RCC RCC_APB2Periph_GPIOB
#define SRCLK_PORT GPIOB
#define SRCLK_PIN GPIO_Pin_3
#define SRCLK_PORT_RCC RCC_APB2Periph_GPIOB
//定义位带
#define RCLK PBout(5)
#define SER PBout(4)
#define SRCLK PBout(3)
.c初始化模板
void LEDS_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体
// 使能GPIO时钟
RCC_APB2PeriphClockCmd(LED_PORT_RCC | RCLK_PORT_RCC, ENABLE);
// GPIOB3,4需要重定向
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 使能复用功能时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); // 关闭JTAG接口
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE); // 关闭SWD接口
GPIO_InitStructure.GPIO_Pin = LED_PIN; //初始化pin
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //初始化模式是推挽
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//频率
GPIO_Init(LED_PORT, &GPIO_InitStructure); //初始化 组 加结构体指针
GPIO_InitStructure.GPIO_Pin = RCLK_PIN | SER_PIN | SRCLK_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(RCLK_PORT, &GPIO_InitStructure);
}
//寄存器输出
static void _WriteByte(u8 u8data)
{
// u16 portVal=GPIO_ReadOutputData(LED_PORT);//读取寄存器数据是16位
// portVal &=0xFF00; //初始化低8位
// portVal |=u8data;//重载低8位
// GPIO_Write(LED_PORT,portVal); //写寄存器数据
// // 输出数据
LED_PORT->ODR = (LED_PORT->ODR & 0xFF00) | u8data;
}