534 lines
14 KiB
C
534 lines
14 KiB
C
#include "gd32e23x.h"
|
||
#include "gd32e230c_lcd_eval.h"
|
||
#include "tft_test.h"
|
||
#include "systick.h"
|
||
|
||
|
||
|
||
#define ARRAYSIZE 4
|
||
uint8_t spi0_send_array[ARRAYSIZE] = {0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA};
|
||
uint8_t spi1_send_array[ARRAYSIZE] = {0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA};
|
||
uint8_t spi0_receive_array[ARRAYSIZE];
|
||
uint8_t spi1_receive_array[ARRAYSIZE];
|
||
|
||
uint32_t send_n = 0, receive_n = 0;
|
||
|
||
|
||
// 新增全局变量
|
||
volatile uint8_t high_level_event = 0; // PA3中断事件标志
|
||
/* 新增函数声明 */
|
||
void exti_pa3_config(void);
|
||
void timer14_config(void);
|
||
|
||
// PA3外部中断服务函数
|
||
void EXTI2_3_IRQHandler(void)
|
||
{
|
||
if(RESET != exti_interrupt_flag_get(EXTI_3)) // PA3引脚出现高电平 → 触发外部中断
|
||
{
|
||
/* 清除中断标志位 */
|
||
exti_interrupt_flag_clear(EXTI_3);
|
||
|
||
/* 设置事件标志 */
|
||
high_level_event = 1;
|
||
|
||
/* 启动定时器,40ms后清除事件标志 */
|
||
// timer_disable(TIMER14);
|
||
timer_counter_value_config(TIMER14, 0);
|
||
|
||
timer_enable(TIMER14);
|
||
}
|
||
}
|
||
|
||
// 定时器14中断服务函数
|
||
void TIMER14_IRQHandler(void)
|
||
{
|
||
if(SET == timer_flag_get(TIMER14, TIMER_FLAG_UP))
|
||
{
|
||
/* 清除定时器中断标志 */
|
||
timer_flag_clear(TIMER14, TIMER_FLAG_UP);
|
||
|
||
/* 禁用定时器 */
|
||
// timer_disable(TIMER14);
|
||
|
||
/* 清除事件标志 */
|
||
high_level_event = 0;
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
void exti_pa3_config(void)
|
||
{
|
||
/* 使能GPIOA时钟 */
|
||
rcu_periph_clock_enable(RCU_GPIOA);
|
||
|
||
/* 配置PA3为上拉输入 */
|
||
gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_3);
|
||
|
||
/* 使能SYSCFG时钟 */
|
||
// rcu_periph_clock_enable(RCU_CFGCMP);
|
||
|
||
/* 连接EXTI线3到PA3 */
|
||
syscfg_exti_line_config(EXTI_SOURCE_GPIOA, EXTI_SOURCE_PIN3);
|
||
|
||
/* 配置EXTI线3 */
|
||
exti_init(EXTI_3, EXTI_INTERRUPT, EXTI_TRIG_RISING);
|
||
exti_interrupt_flag_clear(EXTI_3);
|
||
|
||
/* 使能并配置EXTI中断 */
|
||
nvic_irq_enable(EXTI2_3_IRQn, 2); // 优先级 2(0~3)
|
||
}
|
||
|
||
/* 配置定时器1 */
|
||
void timer14_config(void)
|
||
{
|
||
/* 使能定时器14时钟 */
|
||
rcu_periph_clock_enable(RCU_TIMER14);
|
||
|
||
/* 定时器去初始化 */
|
||
timer_deinit(TIMER14);
|
||
|
||
/* 定时器配置 */
|
||
timer_parameter_struct timer_initpara;
|
||
timer_struct_para_init(&timer_initpara);
|
||
|
||
/* 系统时钟为48MHz,预分频48,计数到40000,产生40ms中断 */
|
||
timer_initpara.prescaler = 71999; // 72MHz / 72000 = 1kHz
|
||
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
|
||
timer_initpara.counterdirection = TIMER_COUNTER_UP;
|
||
timer_initpara.period = 199; // 40ms (0~39)
|
||
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
|
||
timer_initpara.repetitioncounter = 0;
|
||
timer_init(TIMER14, &timer_initpara);
|
||
|
||
/* 使能定时器更新中断 */
|
||
timer_interrupt_enable(TIMER14, TIMER_INT_FLAG_UP);
|
||
|
||
/* 配置定时器中断 */
|
||
nvic_irq_enable(TIMER14_IRQn, 1); // 优先级 1(高于 EXTI)
|
||
|
||
/* 定时器初始状态为禁用,等待中断触发 */
|
||
// timer_disable(TIMER14);
|
||
|
||
// ✅ 启动定时器,让它一直运行
|
||
timer_enable(TIMER14);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
void test_status_led_init(void);
|
||
void flash_led(uint32_t times);
|
||
/*!
|
||
\brief main function
|
||
\param[in] none
|
||
\param[out] none
|
||
\retval none
|
||
*/
|
||
void motor_stop(void)
|
||
{
|
||
/* close all of leds */
|
||
gd_eval_led_off(LED1);
|
||
gd_eval_led_off(LED2);
|
||
gd_eval_led_off(LED3);
|
||
gd_eval_led_off(LED4);
|
||
}
|
||
|
||
const uint8_t phasecw[8] =
|
||
|
||
{0x08, 0x0c, 0x04, 0x06, 0x02, 0x03, 0x01, 0x09};
|
||
|
||
// 逆时针
|
||
|
||
// 1000,1100,0100,0110,0010,0011,0001,1001
|
||
|
||
const uint8_t phaseccw[8] =
|
||
|
||
{0x09, 0x01, 0x03, 0x02, 0x06, 0x04, 0x0c, 0x08};
|
||
|
||
// 顺时针
|
||
|
||
// 1001,0001,0011,0010,0110,0100,1100,1000
|
||
|
||
// 引脚映射
|
||
|
||
void SetMotor(uint8_t InputData)
|
||
|
||
{
|
||
|
||
if (InputData & 0x01)
|
||
|
||
{
|
||
|
||
gd_eval_led_on(LED4);
|
||
}
|
||
|
||
else
|
||
|
||
{
|
||
|
||
gd_eval_led_off(LED4);
|
||
}
|
||
|
||
if (InputData & 0x02)
|
||
|
||
{
|
||
|
||
gd_eval_led_on(LED3);
|
||
}
|
||
|
||
else
|
||
|
||
{
|
||
|
||
gd_eval_led_off(LED3);
|
||
}
|
||
|
||
if (InputData & 0x04)
|
||
|
||
{
|
||
|
||
gd_eval_led_on(LED2);
|
||
}
|
||
|
||
else
|
||
|
||
{
|
||
|
||
gd_eval_led_off(LED2);
|
||
}
|
||
|
||
if (InputData & 0x08)
|
||
|
||
{
|
||
|
||
gd_eval_led_on(LED1);
|
||
}
|
||
|
||
else
|
||
|
||
{
|
||
|
||
gd_eval_led_off(LED1);
|
||
}
|
||
}
|
||
|
||
// 步距角5.625 360/5.625=64 减速比1/64
|
||
|
||
// 故64*64个脉冲转一圈
|
||
|
||
// n圈数
|
||
|
||
// position 方向
|
||
|
||
void motorNcircle(int n, uint8_t position,uint32_t cycle) // n为步进电机转动的圈数,position为正转或者反转
|
||
|
||
{
|
||
|
||
int i, j, k = 0;
|
||
|
||
for (j = 0; j < n; j++)
|
||
|
||
{
|
||
|
||
for (k = 0; k < 8; k++)
|
||
|
||
{
|
||
|
||
if (1 == position)
|
||
|
||
{
|
||
|
||
SetMotor(phasecw[k]);
|
||
}
|
||
|
||
else
|
||
|
||
{
|
||
|
||
SetMotor(phaseccw[k]);
|
||
}
|
||
|
||
delay_ms(cycle);
|
||
}
|
||
|
||
// }
|
||
}
|
||
}
|
||
|
||
static void spi1_init(void)
|
||
{
|
||
|
||
|
||
/* enable the gpio clock */
|
||
rcu_periph_clock_enable(RCU_GPIOB);
|
||
rcu_periph_clock_enable(RCU_SPI1);
|
||
rcu_periph_clock_enable(RCU_DMA);
|
||
|
||
|
||
/* configure SPI1 GPIO: NSS/PB12, SCK/PB13, MISO/PB14, MOSI/PB15 */
|
||
gpio_af_set(GPIOB, GPIO_AF_0, GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
|
||
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
|
||
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
|
||
|
||
dma_parameter_struct dma_init_struct;
|
||
dma_struct_para_init(&dma_init_struct);
|
||
|
||
/* configure SPI0 transmit DMA: DMA_CH2 */
|
||
dma_deinit(DMA_CH2);
|
||
dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPI0);
|
||
dma_init_struct.memory_addr = (uint32_t)spi0_send_array;
|
||
dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
|
||
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
|
||
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
|
||
dma_init_struct.priority = DMA_PRIORITY_LOW;
|
||
dma_init_struct.number = ARRAYSIZE;
|
||
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
|
||
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
|
||
dma_init(DMA_CH2, &dma_init_struct);
|
||
/* configure DMA mode */
|
||
dma_circulation_disable(DMA_CH2);
|
||
dma_memory_to_memory_disable(DMA_CH2);
|
||
|
||
/* configure SPI0 receive DMA: DMA_CH1 */
|
||
dma_deinit(DMA_CH1);
|
||
dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPI0);
|
||
dma_init_struct.memory_addr = (uint32_t)spi0_receive_array;
|
||
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
|
||
dma_init_struct.priority = DMA_PRIORITY_HIGH;
|
||
dma_init(DMA_CH1, &dma_init_struct);
|
||
/* configure DMA mode */
|
||
dma_circulation_disable(DMA_CH1);
|
||
dma_memory_to_memory_disable(DMA_CH1);
|
||
|
||
/* configure SPI1 transmit DMA: DMA_CH4 */
|
||
dma_deinit(DMA_CH4);
|
||
dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPI1);
|
||
dma_init_struct.memory_addr = (uint32_t)spi1_send_array;
|
||
dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
|
||
dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
|
||
dma_init(DMA_CH4, &dma_init_struct);
|
||
/* configure DMA mode */
|
||
dma_circulation_disable(DMA_CH4);
|
||
dma_memory_to_memory_disable(DMA_CH4);
|
||
|
||
/* configure SPI1 receive DMA: DMA_CH3 */
|
||
dma_deinit(DMA_CH3);
|
||
dma_init_struct.periph_addr = (uint32_t)&SPI_DATA(SPI1);
|
||
dma_init_struct.memory_addr = (uint32_t)spi1_receive_array;
|
||
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
|
||
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
|
||
dma_init(DMA_CH3, &dma_init_struct);
|
||
/* configure DMA mode */
|
||
dma_circulation_disable(DMA_CH3);
|
||
dma_memory_to_memory_disable(DMA_CH3);
|
||
|
||
//spi
|
||
spi_parameter_struct spi_init_struct;
|
||
/* deinitilize SPI and the parameters */
|
||
spi_i2s_deinit(SPI0);
|
||
spi_i2s_deinit(SPI1);
|
||
spi_struct_para_init(&spi_init_struct);
|
||
|
||
/* configure SPI0 parameter */
|
||
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
|
||
spi_init_struct.device_mode = SPI_MASTER;
|
||
spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT;
|
||
spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;
|
||
spi_init_struct.nss = SPI_NSS_HARD;
|
||
spi_init_struct.prescale = SPI_PSC_8;
|
||
spi_init_struct.endian = SPI_ENDIAN_MSB;
|
||
|
||
|
||
/* configure SPI1 parameter */
|
||
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
|
||
spi_init_struct.device_mode = SPI_SLAVE;
|
||
spi_init(SPI1, &spi_init_struct);
|
||
|
||
/* configure SPI1 byte access to FIFO */
|
||
spi_fifo_access_size_config(SPI1, SPI_BYTE_ACCESS);
|
||
|
||
spi_enable(SPI1);
|
||
|
||
|
||
/* enable DMA channel */
|
||
/* SPI1_Tx DMA channel */
|
||
dma_channel_enable(DMA_CH4);
|
||
/* SPI0_Tx DMA channel */
|
||
dma_channel_enable(DMA_CH2);
|
||
/* SPI1_Rx DMA channel */
|
||
dma_channel_enable(DMA_CH3);
|
||
/* SPI0_Rx DMA channel */
|
||
dma_channel_enable(DMA_CH1);
|
||
|
||
/* enable SPI DMA */
|
||
spi_dma_enable(SPI1, SPI_DMA_TRANSMIT);
|
||
spi_dma_enable(SPI1, SPI_DMA_RECEIVE);
|
||
}
|
||
|
||
//周六测试的开始
|
||
|
||
// 全局变量
|
||
uint16_t r_num = 80; // 每个方向全行程固定为 192
|
||
uint8_t motor_switch = 0; // 开关:0 停止,1 运动,初始为停止
|
||
uint8_t motor_repeat = 0;
|
||
uint8_t duration = 0; // 往复运动总秒数
|
||
uint32_t r_cycle = 0; // 每个 motorNcircle 的周期
|
||
uint8_t spi1_receive_array[4] = {0}; // SPI 接收缓冲区:开关、秒数、保留字节
|
||
uint8_t current_direction = 1; // 当前方向:1(右),0(左),初始右移
|
||
uint16_t current_step = 0; // 当前已走步数
|
||
|
||
|
||
// 计算 cycle
|
||
static uint32_t calculate_cycle(uint8_t duration) {
|
||
if (duration == 0) return 0; // 避免除零
|
||
float cycle_float = (duration * 500.0) / (80 * 8); // duration * 500ms / (192 * 8 步)
|
||
return (uint32_t)(cycle_float*10);
|
||
}
|
||
|
||
// 检查并更新 SPI 数据
|
||
static void check_and_update_spi(void) {
|
||
if (dma_flag_get(DMA_CH3, DMA_INT_FLAG_FTF) == SET) {
|
||
dma_flag_clear(DMA_CH3, DMA_INT_FLAG_FTF);
|
||
motor_switch = spi1_receive_array[0]&0x0f; // 更新开关
|
||
motor_repeat = spi1_receive_array[0]>>4;
|
||
duration = spi1_receive_array[1]; // 更新秒数
|
||
r_cycle = calculate_cycle(duration); // 计算周期
|
||
/* 重置 DMA */
|
||
dma_channel_disable(DMA_CH3);
|
||
dma_memory_address_config(DMA_CH3, (uint32_t)spi1_receive_array);
|
||
dma_transfer_number_config(DMA_CH3, 4);
|
||
dma_channel_enable(DMA_CH3);
|
||
}
|
||
}
|
||
|
||
int main(void)
|
||
{
|
||
|
||
/* 配置 systick */
|
||
systick_config();
|
||
/* 初始化测试状态 LED */
|
||
test_status_led_init();
|
||
|
||
/****** 初始化PA3外部中断**** */
|
||
exti_pa3_config();
|
||
|
||
/***** 初始化定时器1**** */
|
||
timer14_config();
|
||
|
||
|
||
/* 上电步进电机归零:125°/0.703125 = 177.7,约 178 个 8 拍,方向 0(限位) */
|
||
motorNcircle(192, 0, 10); // 1.536s,初始归零 p=1ms;
|
||
delay_ms (3000);
|
||
motorNcircle(56, 1, 10);
|
||
/* 初始化 SPI1 */
|
||
spi1_init();
|
||
|
||
while (1) {
|
||
|
||
/* 更新SPI发送数据,将high_level_event状态放在第一个字节 */
|
||
spi1_send_array[0] = high_level_event;
|
||
|
||
/* 检查开关状态 */
|
||
if (motor_switch == 0) {
|
||
motor_stop(); // 停止电机
|
||
check_and_update_spi(); // 检查 SPI 数据
|
||
continue; // 等待开关为 1
|
||
}
|
||
|
||
/* 继续运行:从停止时的方向和步数开始 */
|
||
if (current_direction == 1) { // 右移
|
||
for (; current_step < r_num; current_step++) {
|
||
if (motor_switch == 0) {
|
||
motor_stop();
|
||
break; // 停止并保留当前步数
|
||
}
|
||
if(current_step>20){
|
||
delay_ms(3);
|
||
}
|
||
motorNcircle(1, 1, r_cycle); // 右移 1 次
|
||
check_and_update_spi(); // 检查 SPI 数据
|
||
}
|
||
if (current_step >= r_num) { // 右移完成
|
||
current_direction = 0; // 切换到左移
|
||
current_step = 0; // 重置步数
|
||
}
|
||
} else { // 左移
|
||
for (; current_step < r_num; current_step++) {
|
||
if (motor_switch == 0) {
|
||
motor_stop();
|
||
break; // 停止并保留当前步数
|
||
}
|
||
if(current_step>20){
|
||
delay_ms(3);
|
||
}
|
||
motorNcircle(1, 0, r_cycle); // 左移 1 次
|
||
check_and_update_spi(); // 检查 SPI 数据
|
||
}
|
||
if (current_step >= r_num) { // 左移完成
|
||
current_direction = 1; // 切换到右移
|
||
current_step = 0; // 重置步数
|
||
// motor_switch = 0;
|
||
if(motor_repeat)
|
||
motor_switch = 1;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*!
|
||
\brief test status led initialize
|
||
\param[in] none
|
||
\param[out] none
|
||
\retval none
|
||
*/
|
||
void test_status_led_init(void)
|
||
{
|
||
/* initialize the leds */
|
||
gd_eval_led_init(LED1);
|
||
gd_eval_led_init(LED2);
|
||
gd_eval_led_init(LED3);
|
||
gd_eval_led_init(LED4);
|
||
|
||
/* close all of leds */
|
||
gd_eval_led_off(LED1);
|
||
gd_eval_led_off(LED2);
|
||
gd_eval_led_off(LED3);
|
||
gd_eval_led_off(LED4);
|
||
|
||
}
|
||
|
||
/*!
|
||
\brief flash leds
|
||
\param[in] times: leds blink times
|
||
\param[out] none
|
||
\retval none
|
||
*/
|
||
void flash_led(uint32_t times)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < times; i++)
|
||
{
|
||
/* insert 200 ms delay */
|
||
delay_ms(200);
|
||
|
||
/* turn on leds */
|
||
gd_eval_led_on(LED1);
|
||
gd_eval_led_on(LED2);
|
||
gd_eval_led_on(LED3);
|
||
gd_eval_led_on(LED4);
|
||
|
||
/* insert 200 ms delay */
|
||
delay_ms(200);
|
||
|
||
/* turn off leds */
|
||
gd_eval_led_off(LED1);
|
||
gd_eval_led_off(LED2);
|
||
gd_eval_led_off(LED3);
|
||
gd_eval_led_off(LED4);
|
||
}
|
||
}
|