[AT-START-F425 Review] CAN and N32G45 communication example - controlling the servo by stacking blocks.
[Copy link]
[Preface] Previously, I had already completed the temperature and humidity, RTC display, and used a single machine to debug the servo control. According to my evaluation plan, I used AT32 to communicate with N32G45 and STM32. Today, I completed the dual-machine CAN communication.
[Hardware Construction] AT32F425 is the master controller, N32G45 is the command sender, and the CAN analyzer of STM32F103 is the monitor. Since AT32F425 and N32G45 are not equipped with CAN to TTL chips, I used the transceiver I used for Fudan Micro Evaluation. Fortunately, I bought two at that time, one was used and the other was gathering dust... This time, I finally used both. (Since it is connected by Dubinding wire, please forgive the wires for being a bit messy).
The protagonist of this communication is to use the three buttons of N32G45 to control the servo connected to AT32F425 to perform 0, 90 and 180 degree rotation demonstration. The signal control of the servo is controlled by TMR1 CH1 (PA8). Because the USB power supply is afraid that the current of the motor is not enough, I asked for my GPD DC power supply:
[Software environment] RT_Tread Studio opens the N32G45 and AT32F425 programming environment.
[Main procedures] 1. Read the status of three buttons of N32G45:
void init_Key(void)
{
/* 按键1、2、3引脚为输入模式 */
rt_pin_mode(KEY1_PIN_NUM, PIN_MODE_INPUT_PULLUP);
rt_pin_mode(KEY2_PIN_NUM, PIN_MODE_INPUT_PULLUP);
rt_pin_mode(KEY3_PIN_NUM, PIN_MODE_INPUT_PULLUP);
}
typedef struct {
uint8_t Key1_state;
uint8_t Key2_state;
uint8_t Key3_state;
} _key_state;
_key_state key_state;
static void key_scan(void)
{
uint16_t id = 0x400;
uint8_t dat[8] = {0};
rt_err_t can_send_state;
key_state.Key1_state = rt_pin_read(KEY1_PIN_NUM);
key_state.Key2_state = rt_pin_read(KEY2_PIN_NUM);
key_state.Key3_state = rt_pin_read(KEY3_PIN_NUM);
if (key_state.Key1_state == 0 || key_state.Key2_state == 0 || key_state.Key3_state ==0) {
dat[0] = key_state.Key1_state;
dat[1] = key_state.Key2_state;
dat[2] = key_state.Key3_state;
can_send_state = can1_send_dat(id,dat);
if (can_send_state != RT_EOK) {
rt_kprintf("send dat fail ERROR:%d\n" , can_send_state );
rt_thread_mdelay(100);
}
}
}
N32G45 sends CAN data:
rt_err_t can1_send_dat(uint16_t send_id,uint8_t *dat)
{
struct rt_can_msg msg = {0};
msg.id = send_id; /* ID 为 0x123 */
msg.ide = RT_CAN_STDID; /* 标准格式 */
msg.rtr = RT_CAN_DTR; /* 数据帧 */
msg.len = 8; /* 数据长度为 8 */
/* 待发送的 8 字节数据 */
msg.data[0] = dat[0];
msg.data[1] = dat[1];
msg.data[2] = dat[2];
msg.data[3] = dat[3];
msg.data[4] = dat[4];
msg.data[5] = dat[5];
msg.data[6] = dat[6];
msg.data[7] = dat[7];
/* 发送一帧 CAN 数据 */
int size = rt_device_write(can1_dev, 0, &msg, sizeof(msg));
if (size < 0)
{
rt_kprintf("can1 dev write data failed rc:%d\n",size);
return RT_ETIMEOUT;
}
return RT_EOK;
}
N32G45 adds the task of sending CAN:
tid_key_scan = rt_thread_create("key_scan",
thread1_entry,
RT_NULL, 512, THREAD_PRIORITY, THREAD_TIMESLICE);
if (tid_key_scan != RT_NULL) {
rt_thread_startup(tid_key_scan);
}
After the N32G45 program is written, download it to the development board and capture data on the CAN analysis after pressing a button:
【AT32F425can data reception and processing】
1. Add the servo driver files rudder.h and rudder.c: configure timer 1, PA8 outputs 50Hz waveform (for details, see my previous post: [New reminder] [AT-START-F425 evaluation] TMR servo driver - domestic chip exchange - Electronic Engineering World Forum (eeworld.com.cn) )
#ifndef __RUDDER_H
#define __RUDDER_H
#include "at32f425.h"
void rudder_init(void);
void set_rudder(uint8_t angle);
#endif
#include "rudder.h"
#include "at32f425_board.h"
#include "at32f425_clock.h"
#include "rtthread.h"
void rudder_init(void)
{
uint32_t timer_period = 0;
uint16_t channel1_pulse = 0;
gpio_init_type gpio_init_struct = {0};
tmr_output_config_type tmr_output_struct;
crm_clocks_freq_type crm_clocks_freq_struct = {0};
crm_clocks_freq_get(&crm_clocks_freq_struct);
/* enable tmr1/gpioa/gpiob clock */
crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
/* timer1 output pin Configuration */
gpio_init_struct.gpio_pins = GPIO_PINS_8 ;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init(GPIOA, &gpio_init_struct);
gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE8, GPIO_MUX_2);
timer_period = (crm_clocks_freq_struct.sclk_freq/12000) - 1;
tmr_base_init(TMR1, timer_period, 229);
tmr_cnt_dir_set(TMR1, TMR_COUNT_UP);
/* channel 1 in output mode */
tmr_output_default_para_init(&tmr_output_struct);
tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_B;
tmr_output_struct.oc_output_state = TRUE;
tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_LOW;
tmr_output_struct.oc_idle_state = TRUE;
tmr_output_struct.occ_output_state = TRUE;
tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;
tmr_output_struct.occ_idle_state = FALSE;
/* channel 1 */
tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_1, &tmr_output_struct);
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_1, channel1_pulse);
/* output enable */
tmr_output_enable(TMR1, TRUE);
/* enable tmr1 */
tmr_counter_enable(TMR1, TRUE);
}
/**
* [url=home.php?mod=space&uid=159083]@brief[/url] 设置舵机角度
* @param angle: 角度值 1-180度
*
*
* @param
* @param
* @retval none
*/
void set_rudder(uint8_t angle)
{
uint16_t pluse;
if(angle >=180)
{
pluse = 229 + 790;
}
else if(angle == 0)
{
pluse = 229;
}
else{
pluse = (uint16_t)(((uint32_t)angle * 795)/180) + 229 ;
}
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_1, pluse);
//rt_thread_mdelay(100);
}
Director adds monitoring CAN program:
static void tid_rudder_entry(void *parameter)
{
while(1)
{
if(rud_engle.flage == 1)
{
rud_engle.flage = 0;
set_rudder(rud_engle.angle);
rt_thread_mdelay(200);
}
rt_thread_mdelay(5);
}
}
tid_rudder = rt_thread_create("RUDDER",
tid_rudder_entry, RT_NULL,
KEY_THREAD_STACK_SIZE,
THREAD_PRIORITY, THREAD_TIMESLICE);
/* 如果获得线程控制块,启动这个线程 */
if (tid_rudder != RT_NULL)
rt_thread_startup(tid_rudder);
Then it's OK, see the effect in the video.
[Feelings] The CAN communication of AT32F425 is easy to use, and the dual-machine communication is smooth, of course, this is still due to the RT-Thread operating system. There is no need to consider the complex logic processing of the bare machine. Of course, there are still many details that have not been handled well. During this period, I get up at 6 o'clock in the morning, plus the time after work, my life is a straight line, going to work, going home, studying, writing code, debugging, writing reports, my life is fulfilling, and I feel that there is not enough time. Tomorrow is a holiday, so I can do my homework well.
|