TA的每日心情 | 开心 2013-7-2 13:29 |
---|
签到天数: 1 天 连续签到: 1 天 [LV.1]初来乍到
|
本帖最后由 shen2008jie 于 2013-8-20 13:15 编辑
好了接着昨天的写了的宏定义和一个初始化函数:
/* 宏定义 -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- ----- */
//IO方向设置宏定义
#define SDA _pin 1
#define GPIOXX GPIOD
#define SDA_IN() {GPIOXX-> MODER &=~((0x00000003)<<(2* pinpos )); GPIOXX-> MODER |= (((uint32_t) 0x00 ) << ( SDA _pin * 2)); } //这里GPIO XX-> MODER选的是D的
#define SDA_OUT() {GPIOXX-> MODER &=~((0x00000003)<<(2* pinpos )); GPIOXX-> MODER |= (((uint32_t) 0x01 ) << ( SDA _pin * 2)); } //这里GPIO XX-> MODER选的是D的
//IO操作函数宏定义
#define IIC_SCL_1 GPIO_SetBits(GPIOD, GPIO_Pin_0)
#define IIC_SCL_0 GPIO_ResetBits(GPIOD, GPIO_Pin_0)
#define IIC_SDA_1 GPIO_SetBits(GPIOD, GPIO_Pin_1)
#define IIC_SDA_0 GPIO_ResetBits(GPIOD, GPIO_Pin_1) //输入SDA #define READ_SDA GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_1)
/* 初始化IIC -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- ----- */
---------函数名 IIC_Init
---------输入无
---------输出无
---------
---------
/* 初始化IIC -------- -------- -------- -------- -------- -------- -------- -------- -------- -------- ----- */
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//悬空
GPIO_Init(GPIOB, &GPIO_InitStructure);
IIC_SCL_1;//管脚置高
IIC_SDA_1; //管脚置高
}
今天继续移植模拟的IIC也就是C51中的代码使用到STM32中。
在徐州工程学院(开发手册)STM32和zigbee技术文档杂记(1)中已经给出C51IIC的管脚的模拟代码
首先我们开始改这个函数代码:
/*******************************************************************
起动总线函数
函数原型: void Start_I2c();
功能: 启动I2C总线,即发送I2C起始条件.
********************************************************************/
void Start_I2c()
{
SDA2=1; /*发送起始条件的数据信号*/
_Nop();
SCK2=1;
_Nop(); /*起始条件建立时间大于4.7us,延时*/
_Nop();
_Nop();
_Nop();
_Nop();
SDA2=0; /*发送起始信号*/
_Nop(); /* 起始条件锁定时间大于4μs*/
_Nop();
_Nop();
_Nop();
_Nop();
SCK2=0; /*钳住I2C总线,准备发送或接收数据 */
_Nop();
_Nop();
}
这个事IIc的启动头信号代码。代码中有五个事件:SDA2=1; _Nop();SCK2=1; SDA2=0; SCK2=0;
分析这五个代码
SDA2=1;
这一句很容就明白是SDA置高,并且是由STM32给芯片信号,也就是输出模式所以根据昨天的STM32F4的解析
看上面的宏定义后就知道改成
IIC_SDA_1;
类似的SCK2=1; SDA2=0; SCK2=0;改成
IIC_SCL_1; IIC_SDA_0; IIC_SCL_0;
好了,那么就要解决_Nop();了
由于这是移植,不是优化,所以我们完全将其代码原封不动的移植过来,所以时间上也调成一样的。
在C51中代码时间约为1US。所以在STM32中设置1US的延迟
————————————止步
这篇的核心就将怎么写具体的延时函数。
下面有事一个较为麻烦的事儿。对于不准确的延时,只要空跑代码就行。看时钟就行,但是这里我将只用较为准确的延时。
这里就涉及到STM32的
在core_cm4.h文件中
/** \brief Structure type to access the System Timer (SysTick). */
typedef struct
{
__IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
__IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
__IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
__I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;
系统定时器,其中有四个参数:控制状态寄存器,重载寄存器,当前值寄存器,校准寄存器
那么我们先用做的就是SYSCLK初始化①:系统时钟选用什么时钟源。
在misc.h中有代码:
/** @defgroup MISC_SysTick_clock_source
* @{
*/
#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB)
#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004)
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
((SOURCE) == SysTick_CLKSource_HCLK_Div8))
还有下方有这个函数
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);
查看这个函数:
/**
* @brief Configures the SysTick clock source.
* @param SysTick_CLKSource: specifies the SysTick clock source.
* This parameter can be one of the following values:
* @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.
* @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.
* @retval None
*/
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
/* Check the parameters */
assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
{
SysTick->CTRL |= SysTick_CLKSource_HCLK;
}
else
{
SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
}
}
SysTick_CLKSource_HCLK_Div8: AHB时钟除以8选为SysTick时钟源。
SysTick_CLKSource_HCLK:SysTick AHB时钟选为时钟源。
那我们就在初始化函数中选用这个函数SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟HCLK/8
SYSTICK的时钟固定为HCLK时钟的1/8
那么初始化函数大概可以这样写:
void SysTick_Delay_init()
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//选择外部时钟HCLK/8 SYSTICK的时钟固定为HCLK时钟的1/8
}
但是由于系统时钟是可以设置的,那么就设置一个输入参数,这样就不局限了。
void SysTick_Delay_init(u8 Sys_clk)//Sys_clk单位是M。
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//选择外部时钟HCLK/8 SYSTICK的时钟固定为HCLK时钟的1/8
}
Sys_clk输入参数也影响到us、ms的装载的值。所以还要设置一个中间静态变量static u8 MID_us=0;、
static u16 MID_ms=0;//us、ms延时装载时要乘上的数
那么改初始化程序为:
void SysTick_Delay_init(u8 Sys_clk)//Sys_clk单位是M。
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//选择外部时钟HCLK/8 SYSTICK的时钟固定为HCLK时钟的1/8
MID_us=Sys_clk/8; // 由于八分频所以除以8 MID_ms=(u16)MID_us*1000;//一毫秒等于1000微妙
}
那么对于ms:由于SysTick->LOAD为24位寄存器,所以,最大延时为:MAX_ms<=0xffffff*8*1000/(Sys_Ck*10^6)
Sys_Ck单位为M,MAX_ms单位为ms
//对72M条件下,MAX_ms<=1864.135
那么写一个延时函数:这里原理就是51中设置预装定制值,开定时器,寻查到点的标志位,然后跳出循环,清除标志和装定制,就OK了。
那么写出代码:
计数器记一次就是8/(Sys_Ck*10^6)秒。对于72M那么Sys_Ck=72.
那么现在就可以知道为什么要有
MID_us=Sys_clk/8; // 由于八分频所以除以8 MID_ms=(u16)MID_us*1000;//一毫秒等于1000微妙
这两个数,这两个数乘上计数器一次的值就等于1.
假设我要延时一毫秒,那么装载的数值为0.001/{8/(Sys_Ck*10^6)}=Sys_clk/8*1000== MID_ms;
那么下面就是延时代码:
void Delay_ms(u16 ms)
{
u32 t;
SysTick->LOAD=(u32)ms*MID_ms;//时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空当前值计数器
SysTick->CTRL=0x01 ; //开始倒数
do
{
t=SysTick->CTRL;
}
while(!(t&(1<<16))&&t&0x01);//判断时间是否到达
SysTick->CTRL=0x00; //清除控制寄存器
SysTick->VAL =0X00; //清空当前值
}
类似的US的代码:复制改一下MID_us,us。
void Delay_us(u16 us)
{
u32 t;
SysTick->LOAD=(u32)us*MID_us;//时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空当前值计数器
SysTick->CTRL=0x01 ; //开始倒数
do
{
t=SysTick->CTRL;
}
while(!(t&(1<<16))&&t&0x01);//判断时间是否到达
SysTick->CTRL=0x00; //清除控制寄存器
SysTick->VAL =0X00; //清空当前值
}
那么在函数中建一个.h和.c包含以下就行了
。
那么延时一毫秒只要Delay_us(1);
分割线————————————————————
对于那个_Nop();现在只要
宏定义:
#define Delay_us(1) _Nop()
就行了。
总结一下:这篇主要讲了配置系统定时器,实现准确延时。还更改了IIc的开始函数。
今天就到这里。
今天由于得到一个很不好的消息,我的大妈突然得病住院,而且情形很严重,很严重。
,可能这一段时间没心情也没时间写,所以更新会慢一点了。
|
-
|