【AT-START-F425测评】CAN与N32G45通讯实例—堆积木之控制舵机。
[复制链接]
【前言】前面积木堆到了温湿度、RTC显示,又用单机调试了舵机的控制。根据我的评测计划是用AT32与N32G45以及STM32进行通信。今天堆积木到了双机CAN通信。
【硬件搭建】AT32F425为主控方,N32G45为指令发送,STM32F103的CAN分析仪为监控方。由于AT32F425、N32G45没有配置CAN转TTL芯片,所以请出了我原来用于复旦微测评的收发器,还好当时我买了两块,备着一块使用,另一块吃灰的。。。这次终于两块都用上了。(由于用的是杜绑线连接,原谅线有点乱)。
这次通信的主角是用N32G45的三个按键来控制接在AT32F425上的舵机进行0度、90度、180度的旋转演示。舵机的信号控制由TMR1 CH1(PA8)来控制,因为USB供电驱动电机怕有电流不够,所以请出了我的GPD直流电源:
【软件环境】RT_Tread Studio开启N32G45、AT32F425编程环境。
【主要程序】1、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发送CAN数据:
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加入发送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);
}
N32G45程序编写结束后下载到开发板,按键后在CAN分析上捕获数据:
【AT32F425can数据接收与处理】
1、添加舵机驱动文件rudder.h、rudder.c:配置定时器1,PA8输出50Hz波形(具体见我上一篇贴子:【新提醒】【AT-START-F425测评】TMR 舵机驱动 - 国产芯片交流 - 电子工程世界-论坛 (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);
}
主任添加监控CAN程序:
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);
然后就OK了,效果见视频。
【感受】AT32F425的CAN通信上手还算顺手,双机通信实现起来顺利,当然这还是归功于RT—Thread的操作系统。不用考虑祼机的复杂逻辑处理。当然还有许多细节没有处理好。这段时间都是早上6点起来,加上下班时间,生活两点一线,上班下班,学习,写代码,调试,写报告,生活充实,感觉时间不够用。明天马上放假了,可以好好写作业。
|