逐飞科技STC32G12K128开源库学习(基础)

GPIO

电平读取与改变(GPI & GPO)

读电平貌似是直接用引脚号就行,貌似默认拉高。(从led的点亮方式来看,输出也应该是直接赋值即可)

//示例

#include "headfile.h"

#define LED P52

void main()
{
	board_init();			
	
    while(1)
	{
		//将 P04 接地,就可观察到灯灭
		if(P04 == 1)
			LED = 0;
		else
			LED = 1;
    }
}

模式设定

gpio_mode(P5_4, GPO_PP);

//-------------------------------------------------------------------------------------------------------------------
//  @brief      GPIO设置引脚模式
//  @param      pin         选择引脚(P0_0-P5_4)
//  @param      mode        引脚模式 GPIO:准双向口, GPO_PP:推挽输出, GPI_IMPEDANCE:高阻输入, GPI_OD:开漏输出
//  @return     void
//  Sample usage:           gpio_mode(P0_0,GPIO);       // 设置P0.0设置为双向IO
//-------------------------------------------------------------------------------------------------------------------
void gpio_mode(PIN_enum pin, GPIOMODE_enum mode)

typedef enum
{
    //pnm1 pnm0
    GPIO = 0,            //准双向口(弱上拉)
    GPO_PP = 1,            //推挽输出
    GPI_IMPEDANCE = 2,    //高阻输入
    GPI_OD = 3,            //开漏输出
}GPIOMODE_enum;

关于P52 与 P5_2 的区别

P52 是在 STC32Gxx.h 这个官方的文件里定义的,实际上在调用的时候感觉是一个很强大的变量,相当于直接读取或改变相应引脚的电平。可能本质上是 *p 一类的。(本人并没有细究)

P5_2 是在逐飞自己写的头文件里定义的枚举,实际上是个定值,仅在调用逐飞的一些关于gpio的函数里用来确定引脚。

EXTI

//-------------------------------------------------------------------------------------------------------------------
//  @brief      外部中断初始化
//  @param      NULL                
//  @return     void
//  Sample usage:               exit_init(INT0_P32,BOTH) //初始化P32 作为外部中断引脚,双边沿触发。
//-------------------------------------------------------------------------------------------------------------------
void exit_init(INTN_enum int_n,INT_MODE_enum mode)

typedef enum    // 枚举ADC通道
{
    INT0_P32 = 0,    //支持边沿,下降沿中断
    INT1_P33,        //支持边沿,下降沿中断
    INT2_P36,        //支持下降沿中断        
     INT3_P37,        //支持下降沿中断
    INT4_P30,        //支持下降沿中断
}INTN_enum;

typedef enum    // 枚举ADC通道
{
    BOTH,            //边沿
    FALLING_EDGE,    //下降沿
//    RISING_EDGE,    //不支持上升沿

}INT_MODE_enum;

示例:

main.c:

void main()
{
	board_init();			// 初始化寄存器,勿删除此句代码。
	
	// 此处编写用户代码(例如:外设初始化代码等)

    exit_init(INT0_P32, FALLING_EDGE);	//下降沿触发INT0_P32中断
                                        //触发中断LED 就会被点亮

    while(1)
	{

    }
}

isr.c:

#define LED P52
void INT0_Isr() interrupt 0
{
	LED = 0;	//点亮LED
}

PIT

    pit_timer_ms(TIM_4, 1);                //使用TIMER作为周期中断,时间1ms一次
                                        //进入1000次中断 翻转一次LED,也就是1000MS 翻转一次LED

//-------------------------------------------------------------------------------------------------------------------
//  @brief      定时器周期中断
//  @param      tim_n      定时器通道号
//  @param      time_ms    时间(ms)
//  @return     void      
//  Sample usage:          pit_timer_ms(TIM_0, 10)
//                           使用定时器0做周期中断,时间10ms一次。
//-------------------------------------------------------------------------------------------------------------------
void pit_timer_ms(TIMN_enum tim_n,uint16 time_ms)

typedef enum    // 枚举ADC通道
{
    TIM_0,    
    TIM_1,        
    TIM_2,         
    TIM_3,
    TIM_4,
}TIMN_enum;

示例:

main.c:

void main()
{
	board_init();			// 初始化寄存器,勿删除此句代码。
	
	// 此处编写用户代码(例如:外设初始化代码等)

	pit_timer_ms(TIM_4, 1);				//使用TIMER作为周期中断,时间1ms一次
										//进入1000次中断 翻转一次LED,也就是1000MS 翻转一次LED

    while(1)
	{

    }
}

isr.c:

uint32 count = 0;
void TM4_Isr() interrupt 20
{
	TIM4_CLEAR_FLAG; //清除中断标志
    if(count++ >= 1000)
    {
        count = 0;
        LED = !LED;
    }
    
//	ccd_collect();	 //CCD采集数据

}

编码器(脉冲捕获)

从逐飞的库可以看出来,stc是不能用正交式编码器的,只能用较为简单的方向式编码器通过一个脚读电平判断正反转,一个脚记录脉冲数计算转数来手动解算。读电平就用前面的gpio就行了,但是脉冲计数这事儿,因为编码器转一圈产生的脉冲数是非常可观的,你要是想用什么EXTI来手动外部中断就stc这cpu得够呛,所以我们需要用类似于DMA的一种独立的模块来计数(个人理解)。

这就用到了我们计时器的脉冲计数功能。用过stm32的可能都知道,在cube里面配置那些比较高级的定时器的时候它一般都会让我们选择是外部源还是内部源。个人理解定时器本质上就是一个计数器,当使用内部源,也就是我们一般所使用的就是内部晶振产生的源时,该定时器用于定时,数到一定的数量就计一定的时间(一个周期)。

而使用外部源时,其作为定时器的准确性是完全靠不上了,但是他就可以成为一个单纯的计数器,帮我们计算脉冲数。这也正是它可以用来为编码器计数的原因。

值得注意的是,既然我们这个定时器的计数功能给了外部脉冲,那么他就不能通过计数内部脉冲来作为定时器了。换句话讲,就是一个编码器就会占用一个定时器,每个定时器同一时间都只能以一种工作方式工作。(不过stc的pwm不是用定时器产生的不用考虑干扰)。

而stc的定时器本来就不多,tim2又分配给串口做波特率发生器了,所以大家要合理分配定时器资源。

关于具体的使用,直接看例程叭。

#define DIR P35
int16 dat = 0;
void main()
{
	board_init();			// 初始化寄存器,勿删除此句代码。
	
	// 此处编写用户代码(例如:外设初始化代码等)
	
	ctimer_count_init(CTIM0_P34);
	
    while(1)
	{
        if(DIR == 1)
		{
			dat = ctimer_count_read(CTIM0_P34);
		}
		else
		{
			dat = ctimer_count_read(CTIM0_P34) * -1;
		}
		ctimer_count_clean(CTIM0_P34);
		printf("dat = %d\r\n", dat);
		delay_ms(100);
    }
}

//-------------------------------------------------------------------------------------------------------------------
//  @brief      定时器初始化作为外部计数
//  @param      tim_n           选择模块
//  @return     void
//  @since      v1.0
//  Sample usage:               ctimer_count_init(CTIM0_P34);        //初始化定时器0,外部输入为P3.4引脚
//  @note                       串口1使用定时器1作为波特率发生器,
//                                串口2使用定时器2作为波特率发生器,
//                                串口3使用定时器3作为波特率发生器,
//                                串口4使用定时器4作为波特率发生器,
//                              STC16F仅有定时器0-定时器4,这5个定时器。
//                                编码器采集数据也需要定时器作为外部计数。
//-------------------------------------------------------------------------------------------------------------------
void ctimer_count_init(CTIMN_enum tim_n)

//-------------------------------------------------------------------------------------------------------------------
//  @brief      获取计数数值
//  @param      countch     计数通道号及引脚
//  @return     uint32      返回计数值
//  Sample usage:           num = ctimer_count_read(CTIM0_P34);     
//-------------------------------------------------------------------------------------------------------------------
uint16 ctimer_count_read(CTIMN_enum tim_n)

//-------------------------------------------------------------------------------------------------------------------
//  @brief      清除计数数值
//  @param      countch     计数通道号及引脚
//  @return     void      
//  Sample usage:           ctimer_count_clean(CTIM0_P34);     
//-------------------------------------------------------------------------------------------------------------------
void ctimer_count_clean(CTIMN_enum tim_n)

typedef enum    // 枚举ADC通道
{
    CTIM0_P34=0,    
    CTIM1_P35,        
    CTIM2_P12,         
    CTIM3_P04,
    CTIM4_P06,
}CTIMN_enum;

ADC

初始化

adc_init(ADC_P10, ADC_SYSclk_DIV_2);    //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2

//-------------------------------------------------------------------------------------------------------------------
//  @brief      ADC初始化
//  @param      adcn            选择ADC通道
//  @param      speed              ADC时钟频率
//  @return     void
//  Sample usage:               adc_init(ADC_P10,ADC_SYSclk_DIV_2);//初始化P1.0为ADC功能,ADC时钟频率:SYSclk/2
//-------------------------------------------------------------------------------------------------------------------
void adc_init(ADCN_enum adcn,ADC_SPEED_enum speed)

typedef enum
{
    ADC_P10 = 0     , 
    ADC_P11         , 
    ADC_P12         ,    //STC16F没有这个引脚,仅做站位使用
    ADC_P13         , 
    ADC_P14         , 
    ADC_P15         , 
    ADC_P16         , 
    ADC_P17         , 
    
    ADC_P00         , 
    ADC_P01         , 
    ADC_P02            , 
    ADC_P03            , 
    ADC_P04            , 
    ADC_P05            , 
    ADC_P06            , 
    ADC_POWR = 0x0f    , //内部AD 1.19V
} ADCN_enum;

typedef enum
{
    ADC_SYSclk_DIV_2 = 0,
    ADC_SYSclk_DIV_4,
    ADC_SYSclk_DIV_6,
    ADC_SYSclk_DIV_8,
    ADC_SYSclk_DIV_10,
    ADC_SYSclk_DIV_12,
    ADC_SYSclk_DIV_14,
    ADC_SYSclk_DIV_16,
    ADC_SYSclk_DIV_18,
    ADC_SYSclk_DIV_20,
    ADC_SYSclk_DIV_22,
    ADC_SYSclk_DIV_24,
    ADC_SYSclk_DIV_26,
    ADC_SYSclk_DIV_28,
    ADC_SYSclk_DIV_30,
    ADC_SYSclk_DIV_32,
} ADC_SPEED_enum;

调用读值

adc_data[0] = adc_once(ADC_P10, ADC_12BIT);    //采集一次ADC,精度10位

//-------------------------------------------------------------------------------------------------------------------
//  @brief      ADC转换一次
//  @param      adcn            选择ADC通道
//  @param      resolution      分辨率
//  @return     void
//  Sample usage:               adc_convert(ADC_P10, ADC_10BIT);
//-------------------------------------------------------------------------------------------------------------------
uint16 adc_once(ADCN_enum adcn,ADCRES_enum resolution)

typedef enum
{
    ADC_P10 = 0     , 
    ADC_P11         , 
    ADC_P12         ,    //STC16F没有这个引脚,仅做站位使用
    ADC_P13         , 
    ADC_P14         , 
    ADC_P15         , 
    ADC_P16         , 
    ADC_P17         , 
    
    ADC_P00         , 
    ADC_P01         , 
    ADC_P02            , 
    ADC_P03            , 
    ADC_P04            , 
    ADC_P05            , 
    ADC_P06            , 
    ADC_POWR = 0x0f    , //内部AD 1.19V
} ADCN_enum;

typedef enum    // 枚举ADC通道
{

    ADC_12BIT=0,    //12位分辨率
    ADC_11BIT,        //11位分辨率
    ADC_10BIT,        //10位分辨率
    ADC_9BIT,        //9位分辨率
    ADC_8BIT,         //8位分辨率

}ADCRES_enum;

示例:

uint16 adc_data[3];
void main()
{
	board_init();			// 初始化寄存器,勿删除此句代码。
	
	// 此处编写用户代码(例如:外设初始化代码等)
	
    adc_init(ADC_P10, ADC_SYSclk_DIV_2);	
    //初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2

    adc_init(ADC_P11, ADC_SYSclk_DIV_2);	
    //初始化ADC,P1.1通道 ,ADC时钟频率:SYSclk/2

    adc_init(ADC_P13, ADC_SYSclk_DIV_2);	
    //初始化ADC,P1.2通道 ,ADC时钟频率:SYSclk/2

    while(1)
	{
		//使用在线调试,查看adc_data数组的数值,可以得到AD数据。
		adc_data[0] = adc_once(ADC_P10, ADC_12BIT);	//采集一次ADC,精度10位
		adc_data[1] = adc_once(ADC_P11, ADC_10BIT);	//采集一次ADC,精度9位
		adc_data[2] = adc_once(ADC_P13, ADC_8BIT);	//采集一次ADC,精度8位
		printf("adc_data[0] = %d\r\n", adc_data[0]);
		printf("adc_data[1] = %d\r\n", adc_data[1]);
		printf("adc_data[2] = %d\r\n", adc_data[2]);
		
		delay_ms(100);
    }
}

PWM

初始化

pwm_init(PWMB_CH2_P01, 17000, 0);  

 //初始化PWMB_CH2_P01  输出PWM频率17000HZ   占空比为百分之 pwm_duty / PWM_DUTY_MAX * 100

//-------------------------------------------------------------------------------------------------------------------
//  @brief      PWM初始化
//  @param      pwmch       PWM通道号及引脚
//  @param      freq        PWM频率(10Hz-3MHz)
//  @param      duty        PWM占空比
//  @return     void
//  Sample usage:           
//                            pwm_init(PWM0_P00, 100, 5000);     //初始化PWM0  使用引脚P0.0  输出PWM频率100HZ   占空比为百分之 5000/PWM_DUTY_MAX*100
//                            PWM_DUTY_MAX在zf_pwm.h文件中 默认为10000
//-------------------------------------------------------------------------------------------------------------------
void pwm_init(PWMCH_enum pwmch,uint32 freq, uint32 duty)

typedef enum
{
    //PWMA和PWMB是两组不同的PWM
    
    //以下是PWMA通道。
    //同一组PWM,同一时刻,只能有同一个PWM输出。
    //例如:PWMA_CH1P_P10 和 PWMA_CH1N_P11不能一起输出。
    PWMA_CH1P_P10 = 0x00,PWMA_CH1N_P11,
    PWMA_CH1P_P20,         PWMA_CH1N_P21,
    PWMA_CH1P_P60,         PWMA_CH1N_P61,

    PWMA_CH2P_P12 = 0x10,//该引脚已做 USB 内核电源稳压脚
    PWMA_CH2N_P13,          
    PWMA_CH2P_P22,         PWMA_CH2N_P23,
    PWMA_CH2P_P62,         PWMA_CH2N_P63,

    PWMA_CH3P_P14 = 0x20,PWMA_CH3N_P15,
    PWMA_CH3P_P24,         PWMA_CH3N_P25,
    PWMA_CH3P_P64,         PWMA_CH3N_P65,

    PWMA_CH4P_P16 = 0x30,PWMA_CH4N_P17,
    PWMA_CH4P_P26,         PWMA_CH4N_P27,
    PWMA_CH4P_P66,         PWMA_CH4N_P67,
    PWMA_CH4P_P34,         PWMA_CH4N_P33,
    
    //以下是PWMB通道。
    //同一组PWM,同一时刻,只能有同一个PWM输出。
    //例如:PWMB_CH1_P20 和 PWMB_CH1_P17 不能同时输出 
    //但是不同的通道可以同一时刻输出。
    //例如:PWMB_CH1_P20 和 PWMB_CH2_P21可以同时输出
    PWMB_CH1_P20 = 0x40,
    PWMB_CH1_P17,
    PWMB_CH1_P00,
    PWMB_CH1_P74,

    PWMB_CH2_P21 = 0x50,
    PWMB_CH2_P54,        //该引脚为复位引脚
    PWMB_CH2_P01,
    PWMB_CH2_P75,

    PWMB_CH3_P22 = 0x60,
    PWMB_CH3_P33,
    PWMB_CH3_P02,
    PWMB_CH3_P76,

    PWMB_CH4_P23 = 0x70,
    PWMB_CH4_P34,
    PWMB_CH4_P03,
    PWMB_CH4_P77,

}PWMCH_enum;

改变占空比

//-------------------------------------------------------------------------------------------------------------------
//  @brief      PWM占空比设置
//  @param      pwmch       PWM通道号及引脚
//  @param      duty        PWM占空比
//  @return     void
//  Sample usage:           pwm_duty(PWM0_P00, 5000);     //初始化PWM0  使用引脚P0.0  输出PWM频率50HZ   占空比为百分之 5000/PWM_DUTY_MAX*100
//                            PWM_DUTY_MAX在fsl_pwm.h文件中 默认为10000
//-------------------------------------------------------------------------------------------------------------------
void pwm_duty(PWMCH_enum pwmch, uint32 duty)

逐飞给的pwm示例看着很神奇,就不引用了

结尾

懂这几个就差不多够用了,看数据直接用 printf + vofa 就行,逐飞都给你配好了

就写到这儿叭。

  • 6
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值