今天来介绍SWM32的时钟配置和GPIO的使用。
单片机要跑起来,时钟必须配置正确,SWM32的时钟相对来说还是比较简单的。具备 4 个时钟源可供使用:
内部高频振荡器(20Mhz),25℃时精度为±1%, 全温度范围的精度为±5%。
内部低频振荡器(32KHz)。
外部振荡器(XTAH),可接 3MHz ~32MHz 频率无源晶振 。
PLL 时钟,可选择内部高频时钟或者外部高频晶体振荡器作为参考时钟源进行倍频。
时钟连接图如下:
涉及到的寄存器不算多,有兴趣的可以仔细研究一下。实际使用时,可以直接调用库函数。
在system_SWM320.c文件中。
void SystemInit(void)
{
SYS->CLKEN |= (1 << SYS_CLKEN_ANAC_Pos);
switch(SYS_CLK)
{
case SYS_CLK_20MHz: //0 内部高频20MHz RC振荡器
switchCLK_20MHz();
break;
case SYS_CLK_40MHz: //1 内部高频40MHz RC振荡器
switchCLK_40MHz();
break;
case SYS_CLK_32KHz: //2 内部低频32KHz RC振荡器
switchCLK_32KHz();
break;
case SYS_CLK_XTAL: //3 外部晶体振荡器(2-30MHz)
switchCLK_XTAL();
break;
case SYS_CLK_PLL: //4 片内锁相环输出
switchCLK_PLL();
break;
}
SYS->CLKDIV &= ~SYS_CLKDIV_SYS_Msk;
SYS->CLKDIV |= (SYS_CLK_DIV << SYS_CLKDIV_SYS_Pos);
SystemCoreClockUpdate();
}
可以看到,程序中通过SYS_CLK选择时钟源,这里的SYS_CLK是一个宏定义。翻到文件最上方,看到涉及时钟配置的一些变量已经宏定义好了,如需修改,直接改这些宏定义的值即可。这里举个例子,使用外部无源晶体,以及PLL,配置时钟到120M。配置如下:
系统时钟 = PLL输出频率 = 8M / 4 * 4 * 30 / 2 = 120M。
其它时钟的选择类似,只要修改这些宏定义的值即可。然后再主函数的开始调用时钟配置函数:
int main(void)
{
SystemInit();//配置时钟
while(1);
}
GPIO的使用也比较简单,可以配置输入输出模式、中断方式等,直接调用GPIO_Init函数即可,该函数也有详细的说明:
/******************************************************************************************************************************************
* 函数名称: GPIO_Init()
* 功能说明: 引脚初始化,包含引脚方向、上拉电阻、下拉电阻、开漏输出
* 输 入: GPIO_TypeDef * GPIOx 指定GPIO端口,有效值包括GPIOA、GPIOB、GPIOC、GPIOM、GPION、GPIOP
* uint32_t n 指定GPIO引脚,有效值包括PIN0、PIN1、PIN2、... ... PIN22、PIN23
* uint32_t dir 引脚方向,0 输入 1 输出
* uint32_t pull_up 上拉电阻,0 关闭上拉 1 开启上拉
* uint32_t pull_down 下拉电阻,0 关闭下拉 1 开启下拉
* 输 出: 无
* 注意事项: GPIOA、GPIOC、GPIOM、GPIOP只有上拉,GPIOB、GPION只有下拉(PN0、PN1、PN2三个引脚有上拉没下拉)
******************************************************************************************************************************************/
void GPIO_Init(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t dir, uint32_t pull_up, uint32_t pull_down)
需要特别注意的是:
GPIOA、GPIOC、GPIOM、GPIOP只有上拉,GPIOB、GPION只有下拉(PN0、PN1、PN2三个引脚有上拉没下拉)
库函数还提供了一些IO读写、翻转的函数:
void GPIO_ClrBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w)
void GPIO_InvBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w)
uint32_t GPIO_GetBits(GPIO_TypeDef * GPIOx, uint32_t n, uint32_t w)
void GPIO_AtomicSetBit(GPIO_TypeDef * GPIOx, uint32_t n)
另外,与其他单片机不同的是,该单片机还有一些特殊的操作需要注意:
当GPIOx的16个引脚中,有些在主循环中操作,有些在中断ISR中操作时,GPIOx的引脚必须都用GPIO_Atomic类型函数操作。
比如,GPIOA0是在主循环中操作的,而GPIOA1是在中断中操作的,这时就需要使用GPIO_Atomic类型的函数。
GPIO的其它复用功能将在后面外设的使用时一并介绍。
测试程序如下:
int main(void)
{
SystemInit();
GPIO_Init(GPIOA, PIN4, 0, 1, 0); //输入,上拉使能,接KEY
GPIO_Init(GPIOA, PIN5, 1, 0, 0); //输出, 接LED
while(1==1)
{
if(GPIO_GetBit(GPIOA, PIN4) == 0) //按键被按下
{
GPIO_SetBit(GPIOA, PIN5);
}
else
{
GPIO_ClrBit(GPIOA, PIN5);
}
}
}
推荐阅读:
STM32CubeMX系列教程
开源按键组件Multi_Button的使用,含测试工程
Keil调试时设置断点的高级用法
电路设计合集
欢迎关注公众号"嵌入式技术开发",大家可以后台给我留言沟通交流。如果觉得该公众号对你有所帮助,也欢迎推荐分享给其他人。