大家好,欢迎来到IT知识分享网。
前言:在学习过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, , TIM_2); //初始化串口1 波特率 发送引脚使用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可选值:,, . , , , , , , , 。 //设置系统频率,此频率需要跟STC-ISP软件中的 <输入用户程序运行的IRC频率>选项的频率一致。 //如果频率设置不对,将会导致串口的数据不正常,PWM的工作不正常等等。 sys_clk = ; //设置系统频率为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可选值:,, . , , , , , , , 。 //设置系统频率,此频率需要跟STC-ISP软件中的 <输入用户程序运行时的IRC频率>选项的频率一致。 //如果频率设置不对,将会导致串口的数据不正常,PWM的工作不正常等等。 //设置系统频率,此频率需要跟STC-ISP软件中的 <输入用户程序运行时的IRC频率>选项的频率一致。 sys_clk = ; //设置系统频率为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); } }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/109890.html