STC32的概述学习(在有STM32学习的基础上)

前言:在学习过STM32后,现在为了打智能车,开始学习STC32。STC32相比于STM32在库函数方面会更加简洁明了,其基本内核都差不多,只是在一些引脚表述上有少许差别,下面我将列举STC32的一些例程来对熟悉这个芯片。

一、内部固件库函数

(1)GPIO配置
//-------------------------------------------------------------------------------
//  @brief      GPIO设置引脚上拉电阻设置
//  @param      pin         选择引脚(P0_0-P7_7)
//  @param      pull        设置上下拉电阻 NOPULL:不设置 PULLUP:上拉
//  @return     void
//  Sample usage:           gpio_pull_set(P0_0,NOPULL);       // 设置P0.0引脚没有上下拉电阻
//-------------------------------------------------------------------------------
void  gpio_pull_set(PIN_enum pin, PULL_enum pull);




//-------------------------------------------------------------------------------
//  @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);
(2)外部中断初始化
//-------------------------------------------------------------------------------------------------------------------
//  @brief      外部中断初始化
//  @param      外部中断类,相当于EXIT0
//  @param     BOTH//边沿
//	           FALLING_EDGE//下降沿           	
//  @return     void
//  Sample usage:               exit_init(INT0_P32,BOTH) //初始化P32 作为外部中断引脚,双边沿触发。
//-------------------------------------------------------------------------------------------------------------------
void exit_init(INTN_enum int_n,INT_MODE_enum mode)

其中INT为stc单片机的外部中断引脚,有INT0123。配置外部中断函数在函数Isr.c里面写。

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

其中的interrupt 0为INT0对应的中断源,用这个代表中断函数是INT0中断引脚对应的中断函数。

以下是各个中断引脚对应的中断源。

void INT0_Isr() interrupt 0
void INT1_Isr() interrupt 2
void INT2_Isr() interrupt 10
void INT3_Isr() interrupt 11
void INT4_Isr() interrupt 16
(3)内部定时器中断
//-----------------------------------------------------------------------------------------
//  @brief      定时器周期中断
//  @param      tim_n      定时器通道号,有TIM_01234
//  @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);




//---------------------------------------------------------------------------------------
//  @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);

定时器的中断一般就用到这个函数。对应的中断函数也有中断源与之对应。

void TM0_Isr() interrupt 1
void TM1_Isr() interrupt 3
void TM2_Isr() interrupt 12
void TM3_Isr() interrupt 19
void TM4_Isr() interrupt 20
(4)ADC
//-----------------------------------------------------------------------------------------
//  @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);
例:adc_init(ADC_P10, ADC_SYSclk_DIV_2);	//初始化ADC,P1.0通道 ,ADC时钟频率:SYSclk/2


//-----------------------------------------------------------------------------------------
//  @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);
例:adc_once(ADC_P10, ADC_12BIT);	//采集一次ADC,精度10位
(5)PWM
//-----------------------------------------------------------------------------------------
//  @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)
例:pwm_init(PWMA_CH1P_P60, 10000, 0);     //初始化PWMA  使用引脚P6.0  输出PWM频率10000HZ   
//占空比为百分之 pwm_duty / PWM_DUTY_MAX * 100,这里先给0,之后有函数可以改占空比



//-------------------------------------------------------------------------------------------------------------------
//  @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_duty(PWM0_P00, 5000);    //初始化PWM0  使用引脚P0.0  输出



//-------------------------------------------------------------------------------------------------------------------
//  @brief      PWM频率设置
//  @param      pwmch       PWM通道号及引脚
//  @param      freq        PWM频率(10Hz-3MHz)
//  @param      duty        PWM占空比
//  @return     void
//  Sample usage:           pwm_freq(PWM0_P00, 50, 5000);     //修改化PWM0  使用引脚P0.0  输出PWM频率50HZ   占空比为百分之 5000/PWM_DUTY_MAX*100
//-------------------------------------------------------------------------------------------------------------------
void pwm_freq(PWMCH_enum pwmch, uint32 freq, uint32 duty);
例:pwm_freq(PWM0_P00, 50, 5000);     //修改化PWM0  使用引脚P0.0  注意这边参数还有占空比

stc单片机的PWM输出十分的精简,不需要设置重装载值之类的参数,可以直接填入占空比与对应的输出引脚,不需要写什么输出比较函数。

(6)UART
//---------------------------------------------------------------------------------------
//  @brief      串口初始化
//  @param      uart_n          串口模块号(USART_1,USART_2,USART_3,USART_4)
//  @param      uart_rx_pin     串口接收引脚
//  @param      uart_tx_pin     串口发送引脚
//  @param      baud      		串口波特率
//  @param      tim_n      		使用tim_n作为串口波特率发生器(TIM1-TIM4)
//  @return     NULL          	
//  Sample usage:               uart_init(UART_1, UART1_RX_P30, UART1_TX_P31, 115200, TIM_2);        //初始化串口1 波特率115200 发送引脚使用P31 接收引脚使用P30 ,使用定时器2作为波特率发生器
//  @note                       串口1使用 定时器1或者定时器2 作为波特率发生器。
//								串口2使用 定时器2 			 作为波特率发生器。
//								串口3使用 定时器3或者定时器2 作为波特率发生器。
//								串口4使用 定时器4或者定时器2 作为波特率发生器。
//                              STC32G仅有 定时器0-定时器4,这5个定时器。
//								编码器采集数据也需要定时器作为外部计数。
//								如果不同的串口,使用同一个定时器,串口的波特率以最后一个初始化为准
//-----------------------------------------------------------------------------------------
void uart_init(UARTN_enum uart_n, UARTPIN_enum uart_rx_pin, UARTPIN_enum uart_tx_pin, uint32 baud, TIMN_enum tim_n);



//---------------------------------------------------------------------------------------
//  @brief      串口字节输出
//  @param      uart_n          串口模块号(USART_1,USART_2,USART_3,USART_4)
//  @param      dat             需要发送的字节
//  @return     void        
//  Sample usage:               uart_putchar(UART_1,0xA5);       // 串口1发送0xA5
//---------------------------------------------------------------------------------------
void uart_putchar(UARTN_enum uart_n,uint8 dat);



//---------------------------------------------------------------------------------------
//  @brief      串口发送字符串
//  @param      uart_n          串口模块号(USART_1,USART_2,USART_3,USART_4)
//  @param      *str            要发送的字符串地址
//  @return     void
//  Sample usage:               uart_putstr(UART_1,"i lvoe you"); 
//---------------------------------------------------------------------------------------
void uart_putstr(UARTN_enum uart_n,uint8 *str);



二、外设初始化函数

(1)TFT屏幕

去库函数里面找

#include "SEEKFREE_18TFT.h"
#include "SEEKFREE_18TFT.c"

这里面有驱动函数

(2)带方向的编码器
//定义脉冲引脚
#define SPEEDL_PLUSE   CTIM0_P34
#define SPEEDR_PLUSE   CTIM3_P04
//定义方向引脚
#define SPEEDL_DIR     P35
#define SPEEDR_DIR     P53

int16 templ_pluse = 0;
int16 tempr_pluse = 0;

void main()
{
    WTST = 0;               //设置程序代码等待参数,赋值为0可将CPU执行程序的速度设置为最快
    
	DisableGlobalIRQ();		//关闭总中断
	
    //sys_clk可选值:35000000,30000000, 27000000. 24000000, 22118400, 20000000, 18432000, 12000000, 11059200, 6000000, 5529600。
    //设置系统频率,此频率需要跟STC-ISP软件中的 <输入用户程序运行的IRC频率>选项的频率一致。
    //如果频率设置不对,将会导致串口的数据不正常,PWM的工作不正常等等。
    sys_clk = 35000000;     //设置系统频率为35MHz
    
	board_init();		//初始化
    
	ctimer_count_init(SPEEDL_PLUSE);	//初始化定时器0作为外部计数
	ctimer_count_init(SPEEDR_PLUSE);	//初始化定时器3作为外部计数
//	lcd_init();							//1.8寸TFT初始化
	ips114_init();						//初始化1.14寸IPS屏幕
//	oled_init_spi();					//OLED初始化
	
	EnableGlobalIRQ();					//开启总中断
    while(1)
	{
        //读取采集到的编码器脉冲数
        templ_pluse = ctimer_count_read(SPEEDL_PLUSE);
		tempr_pluse = ctimer_count_read(SPEEDR_PLUSE);

        //计数器清零
        ctimer_count_clean(SPEEDL_PLUSE);
		ctimer_count_clean(SPEEDR_PLUSE);

        //采集方向信息
        if(1 == SPEEDL_DIR)    
        {
            templ_pluse = -templ_pluse;
        }
        else                  
        {
            templ_pluse = templ_pluse;
        }
		if(1 == SPEEDR_DIR)    
        {
            tempr_pluse = -tempr_pluse;
        }
        else                  
        {
            tempr_pluse = tempr_pluse;
        }            
		
		//在TFT上显示,需要初始化1.8寸TFT屏幕,才能使用。
//		lcd_showstr(0, 0, "pluse_l =");			lcd_showint16(8*10, 0, templ_pluse);
//		lcd_showstr(0, 1, "pluse_r =");			lcd_showint16(8*10, 1, tempr_pluse);

		//在1.14IPS屏幕上显示,需要初始化1.14寸ips屏幕,才能使用。
		ips114_showstr(0, 0, "pluse_l =");		ips114_showint16(8*10, 0, templ_pluse);
		ips114_showstr(0, 1, "pluse_r =");		ips114_showint16(8*10, 1, tempr_pluse);
		
		//在OLED屏幕上显示,需要初始化OLED屏幕,才能使用。
//		oled_p6x8str_spi(0, 0, "pluse_l =");	oled_int16_spi(8*10, 0, templ_pluse);
//		oled_p6x8str_spi(0, 1, "pluse_r =");	oled_int16_spi(8*10, 1, tempr_pluse);
		
		//延时100ms
		delay_ms(100);
	}
}
(3)IMU66RA六轴陀螺仪

有库函数用,加速度角速度可以直接读取

#include "SEEKFREE_IMU660RA.h"
#include "SEEKFREE_IMU660RA.c"

例程

#include "headfile.h"


/*
 * 系统频率,可查看board.h中的 FOSC 宏定义修改。
 * board.h文件中FOSC的值设置为0,则程序自动设置系统频率为33.1776MHZ
 * 在board_init中,已经将P54引脚设置为复位
 * 如果需要使用P54引脚,可以在board.c文件中的board_init()函数中删除SET_P54_RESRT即可
 */


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

    
	lcd_init();							//1.8寸TFT初始化
//	ips114_init();						//初始化1.14寸IPS屏幕
//	oled_init_spi();					//OLED初始化
			
//	if(imu660ra_init() == 0)				//六轴陀螺仪初始化
//	{
//		delay_ms(500);
//		printf("imu660ra init try again.\r\n");
//		lcd_showstr(0,6,"OK");
//	}
	imu660ra_init();
	pit_timer_ms(TIM_0, 10);
    while(1)
	{
		imu660ra_get_acc(); 		//获取加速度数据
        imu660ra_get_gyro();    	//获取陀螺仪数据
		
		//在TFT上显示,需要初始化1.8寸TFT屏幕,才能使用。
		lcd_showstr(0, 0, "acc.x=");
		lcd_showstr(0, 1, "acc.y=");
		lcd_showstr(0, 2, "acc.z=");
		lcd_showstr(0, 3, "gyro.x=");
		lcd_showstr(0, 4, "gyro.y=");
		lcd_showstr(0, 5, "gyro.z=");
		lcd_showint16(6*10, 0, imu660ra_acc_x);
		lcd_showint16(6*10, 1, imu660ra_acc_y);
		lcd_showint16(6*10, 2, imu660ra_acc_z);
		lcd_showint16(6*10, 3, imu660ra_gyro_x);
		lcd_showint16(6*10, 4, imu660ra_gyro_y);
		lcd_showint16(6*10, 5, imu660ra_gyro_z);

		printf("acc.z=%d\r\n",  imu660ra_acc_z);
		
		delay_ms(100);
	}
}

(4)舵机

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

	//pwm初始化频率为50hz 舵机居中
	duty = 1.5*10000/20;

	pwm_init(PWMB_CH1_P74, 50, duty);
	
    while(1)
	{
		//计算舵机位置舵机位置   (0.5ms - 2.5ms)ms/20ms * 10000(1000是PWM的满占空比时候的值)
        //舵机最小值为250,   最大值为1250。
		
		//修改duty的值,可以修改舵机最大最小值。
		//例:将PWM_DUTY_MAX设置为1000,则舵机最小值为25,最大值为125。
		//PWM_DUTY_MAX的值在zf_pwm.h的文件中定义。
		
        duty++;
        if(1250 < duty) duty = 250;
        
        //控制舵机达到指定位置
        pwm_duty(PWMB_CH1_P74, duty);
        if(250 == duty) delay_ms(1000); //当从1250的位置   回转到250的位置时   应该使用较长的延时等到舵机达到指定位置
        else            delay_ms(5);
    }
}

(5)逐飞的无线模块

记得打USB模块的驱动

#include "headfile.h"

#define LED P52
/*
 *关于内核频率的设定,可以查看board.h文件
 *在board_init中,已经将P54引脚设置为复位
 *如果需要使用P54引脚,可以在board.c文件中的board_init()函数中删除SET_P54_RESRT即可
 */

uint8 send_buf[] = {0x11, 0x22, 0x33};
uint8 read_buf[10];

uint32 dat_len = 0;

uint8 test_str[] = "seekfree.taobao.com\n";

void main()
{
    WTST = 0;               //设置程序代码等待参数,赋值为0可将CPU执行程序的速度设置为最快
    
	DisableGlobalIRQ();		//关闭总中断
	
    //sys_clk可选值:35000000,30000000, 27000000. 24000000, 22118400, 20000000, 18432000, 12000000, 11059200, 6000000, 5529600。
    //设置系统频率,此频率需要跟STC-ISP软件中的 <输入用户程序运行时的IRC频率>选项的频率一致。
    //如果频率设置不对,将会导致串口的数据不正常,PWM的工作不正常等等。
    
    //设置系统频率,此频率需要跟STC-ISP软件中的 <输入用户程序运行时的IRC频率>选项的频率一致。
    sys_clk = 35000000;     //设置系统频率为35MHz
    //设置系统频率,此频率需要跟STC-ISP软件中的 <输入用户程序运行时的IRC频率>选项的频率一致。
    
	board_init();		//初始化
    //无线转串口模块相关引脚定义在 wireless.h文件中
    wireless_uart_init();

	EnableGlobalIRQ();							//开启总中断
    
    // STC禁止在中断里面发送数据。如果在中断里发送数据就会卡死。
    // STC禁止在中断里面发送数据。如果在中断里发送数据就会卡死。
    // STC禁止在中断里面发送数据。如果在中断里发送数据就会卡死。
    // 发送buf
    wireless_uart_send_buff(test_str, sizeof(test_str)-1);
    while(1)
	{
        // 翻转LED
        LED = !LED;
        // 读取fifo中的内容
        dat_len = wireless_uart_read_buff(read_buf, 10);
        // 如果读取到数据
        if(dat_len != 0)
        {
            // 将读取到的fifo发送出去
            wireless_uart_send_buff(read_buf, (uint16)dat_len);
        }
        delay_ms(500);
	}
}

你可能感兴趣的:(嵌入式硬件)