首页 > 其他分享 >Cortex-A53高端智能影音融合播放系统

Cortex-A53高端智能影音融合播放系统

时间:2024-10-26 09:18:30浏览次数:10  
标签:影音 obj create lv A53 void Cortex include event

1.1项目背景及目标

        随着信息技术的飞速发展,多媒体数据已成为人们日常生活和工作的重要组成部分,用户对于音视频播放软件的需求日益增长。然而,目前市面上的多媒体播放器在功能、性能、用户体验等方面存在较大差异,许多播放器无法满足用户多样化的播放需求。为了填补市场空白,提升我国在多媒体播放器领域的竞争力,本项目团队决定研发一款功能强大、操作简便、界面美观的全格式多媒体播放器。该播放器将支持市面上几乎所有主流和非主流的音视频格式,提供高清播放、字幕功能、音效调节、播放列表管理、网络播放等功能,力求为用户带来极致的播放体验。通过本项目,我们期望为用户提供一款品质卓越、满足个性化需求的多媒体播放器,进一步丰富我国多媒体播放器市场,推动行业的发展。

1.2 项目设计流程图

1.3功能视频演示

功能演示

1.4具体功能演示

1.4.1实现视频的播放和控制功能 (暂停,播放,快进,快退,切换)

1.4.2实现播放器的进度条功能

1.4.3.实现音乐的歌词显示功能 (歌词文件与播放的时间进行匹配显示歌词)

1.5核心代码解析

1.5.1主函数

#include "lvgl/lvgl.h"
#include "lvgl/demos/lv_demos.h"
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include "lvgl/lvgl.h"
#include "cJSON.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "function.h"

static const char * getenv_default(const char * name, const char * dflt)
{
    return getenv(name) ?: dflt;
}

#if LV_USE_LINUX_FBDEV
static void lv_linux_disp_init(void)
{
    const char * device = getenv_default("LV_LINUX_FBDEV_DEVICE", "/dev/fb0");
    lv_display_t * disp = lv_linux_fbdev_create();

    lv_linux_fbdev_set_file(disp, device);
}
#elif LV_USE_LINUX_DRM
static void lv_linux_disp_init(void)
{
    const char * device = getenv_default("LV_LINUX_DRM_CARD", "/dev/dri/card0");
    lv_display_t * disp = lv_linux_drm_create();

    lv_linux_drm_set_file(disp, device, -1);
}
#elif LV_USE_SDL
static void lv_linux_disp_init(void)
{
    const int width  = atoi(getenv("LV_SDL_VIDEO_WIDTH") ?: "800");
    const int height = atoi(getenv("LV_SDL_VIDEO_HEIGHT") ?: "480");

    lv_sdl_window_create(width, height);
}
#else
#error Unsupported configuration
#endif

static void SDL_init()
{
    // 创建SDL鼠标设备
    lv_sdl_mouse_create();
    // 创建SDL鼠标滚轮设备
    lv_sdl_mousewheel_create();
}

static void Event_init()
{
    //创建触摸屏设备
    lv_indev_t * touch = lv_evdev_create(LV_INDEV_TYPE_POINTER, "/dev/input/event0");

    //校准屏幕
    lv_evdev_set_calibration(touch, 0, 0, 1024, 600);
}

//----开始----
///-----结束----/

int main(void)
{
    // 初始化LVGL核心部件
    lv_init();

    /*初始化linux显示设备*/
    lv_linux_disp_init();

    // SDL_init();
    Event_init();

///
// 测试开始 
///

    

    //video_menu();

    //music_menu();

    display_desktop();
    

   

///
 测试结束 //
///
    /*Handle LVGL tasks*/
    while(1) {
        lv_timer_handler();
        usleep(5000);
    }
    return 0;
}

1.5.2播放视频模块

//播放视频
void * play(void * arg)
{
    while(1) {
        // 加载播放器进程
        FILE * fp = popen("mplayer -slave -quiet -input file=/pipe -geometry 0:12 -zoom -x 800 -y 350 dream.avi", "r");
        if(fp == NULL) {
            perror("popen");
            return NULL;
        }

        int fd = open("/pipe", O_WRONLY);
        if(fd < 0) {
            perror("open");
            pclose(fp); // 关闭FILE指针
            return NULL;
        }

        // 实时获取视频的当前时长
        char buf[258];
        while(fgets(buf, sizeof(buf), fp) != NULL) {
            printf("msg = %s", buf);

            // 如果需要从mplayer获取时间位置,则发送命令
            write(fd, "get_time_pos\n", strlen("get_time_pos\n"));
            fflush(fp); // 确保命令被发送

            // 简单的命令响应处理,这里假设mplayer会立即响应
            if(strncmp(buf, "ANS_TIME_POSITION=", 18) == 0) {
                double number;
                if(sscanf(buf, "ANS_TIME_POSITION=%lf", &number) == 1) {
                    printf("提取的数字是: %d\n", (int)number);
                    // 更新数据
                    current_video_duration = (int)number;
                } else {
                    printf("数字提取失败\n");
                }
            }

            // 当视频播放结束时,重置播放器并继续播放
            if(current_video_duration >= total_video_duration_1) {
                // 重置播放器
                write(fd, "seek 0\n", strlen("seek 0\n"));
                fflush(fp);
                // 等待播放器重置
                close(fd);  // 关闭文件描述符
                pclose(fp); // 关闭FILE指针

                printf("播放结束\n");
                sleep(1); // 等待足够的时间让播放器重置
                // 继续播放
                break;
            }
        }
    }

    return NULL;
}

1.5.3播放音乐模块

//播放音乐
void * music(void * arg)
{
    while(!stop_thread_music) {
        // 加载播放器进程
        FILE * fp =
            popen("mplayer -slave -quiet -input file=/pipe -geometry 0:12 -zoom -x 800 -y 350 woluolei.mp3", "r");
        if(fp == NULL) {
            perror("popen");
            return NULL;
        }

        int fd = open("/pipe", O_WRONLY);
        if(fd < 0) {
            perror("open");
            pclose(fp); // 关闭FILE指针
            return NULL;
        }

        // 实时获取视频的当前时长
        char buf[258];
        while(1) {

            fgets(buf, sizeof(buf), fp);
            printf("msg = %s", buf);

            // 如果需要从mplayer获取时间位置,则发送命令
            write(fd, "get_time_pos\n", strlen("get_time_pos\n"));
            fflush(fp); // 确保命令被发送

            // 简单的命令响应处理,这里假设mplayer会立即响应
            if(strncmp(buf, "ANS_TIME_POSITION=", 18) == 0) {
                double number;
                if(sscanf(buf, "ANS_TIME_POSITION=%lf", &number) == 1) {
                    // printf("提取的数字是: %d\n", (int)number);
                    // 更新数据
                    // pthread_mutex_lock(&mux);
                    current_music_duration = (int)number;
                    // pthread_mutex_unlock(&mux);

                } else {
                    printf("数字提取失败\n");
                }
            }

            // usleep(20000); // 10毫秒延时
        }
    }

    return NULL;
}

1.5.4控制视频播放的各类控件

// 控制视频播放
void video_playback_interface()
{
    // 1.创建一个通信管道
    mkfifo("/pipe", 0777);

    // 4.在主线程中创建控制按钮
    create_control_buttons();

    // 5.在主线程中创建进度条
    create_progress_bar(total_video_duration_1);
}

// 创建控制按钮
void create_control_buttons()
{
    // 暂停播放
    lv_obj_t * btn_stop = create_button_with_image(lv_scr_act(), 0, -5, "A:/kj_pic/stop.bmp");
    lv_obj_add_event_cb(btn_stop, my_event_stop, LV_EVENT_CLICKED, NULL);

    // 继续播放
    lv_obj_t * btn_continue = create_button_with_image(lv_scr_act(), 90, -5, "A:/kj_pic/continue.bmp");
    lv_obj_add_event_cb(btn_continue, my_event_continue, LV_EVENT_CLICKED, NULL);

    // 快进
    lv_obj_t * btn_gohead = create_button_with_image(lv_scr_act(), 180, -5, "A:/kj_pic/gohead.bmp");
    lv_obj_add_event_cb(btn_gohead, my_event_gohead, LV_EVENT_CLICKED, 4);

    // 快退
    lv_obj_t * btn_back = create_button_with_image(lv_scr_act(), -90, -5, "A:/kj_pic/back.bmp");
    lv_obj_add_event_cb(btn_back, my_event_back, LV_EVENT_CLICKED, 4);

    // 下一首
    lv_obj_t * btn_next = create_button_with_image(lv_scr_act(), 270, -5, "A:/kj_pic/next.bmp");
    lv_obj_add_event_cb(btn_next, my_event_next, LV_EVENT_CLICKED, 4);

    // 上一首
    lv_obj_t * btn_fear = create_button_with_image(lv_scr_act(), -180, -5, "A:/kj_pic/fear.bmp");
    lv_obj_add_event_cb(btn_fear, my_event_fear, LV_EVENT_CLICKED, 4);
}

//         get_percent_pos
//         打印出文件中的当前位置为整数百分比[0-100)。

//创建进度条
lv_obj_t * create_progress_bar(int total_video_duration)
{
    int m = 0;
    int s = 0;

    /* 4. 创建一个进度条 */
    slider = lv_slider_create(lv_scr_act());           // 创建一个进度条,并添加到当前活动的屏幕
    lv_obj_set_size(slider, 800, 10);                  // 设置进度条的宽度和高度
    lv_obj_align(slider, LV_ALIGN_BOTTOM_MID, 0, -90); // 将按钮居中放置

    /* 5. 设置进度条的值范围 */
    lv_slider_set_range(slider, 0, 100); // 设置最小值为0,最大值为100

    //创建两个标签表示当前视频时间 和 总视频时间
    //创建表示当前视频时间标签
    label_pos = lv_label_create(lv_scr_act());
    lv_obj_set_style_text_font(label_pos, &lv_font_montserrat_16, 0); // 设置标签文本
    lv_label_set_text(label_pos, "00:00");
    lv_obj_align_to(label_pos, slider, LV_ALIGN_OUT_BOTTOM_LEFT, 5, 5); // 将标签居中放置在按钮上

    //创建表示总视频时间标签
    label_total = lv_label_create(lv_scr_act());
    lv_obj_set_style_text_font(label_total, &lv_font_montserrat_16, 0); // 设置标签文本
    m             = total_video_duration / 60;
    s             = total_video_duration % 60;
    char temp[50] = {0};
    if(s <= 9) {
        sprintf(temp, "0%d:0%d", m, s);
    } else {
        sprintf(temp, "0%d:%d", m, s);
    }
    lv_label_set_text(label_total, temp);
    lv_obj_align_to(label_total, slider, LV_ALIGN_OUT_BOTTOM_RIGHT, -5, 5); // 将标签居中放置在按钮上

    return NULL;
}

//更新当前视频时间
void * update_the_current_video_time(void * arg)
{
    //初始化锁
    pthread_mutex_init(&mux, NULL);

    while(1) {
        int m = 0;
        int s = 0;

        m = current_video_duration / 60;
        s = current_video_duration % 60;

        char temp[50] = {0};
        if(s <= 9) {
            sprintf(temp, "0%d:0%d", m, s);
        } else {
            sprintf(temp, "0%d:%d", m, s);
        }

        pthread_mutex_lock(&mux);
        lv_label_set_text(label_pos, temp);
        pthread_mutex_unlock(&mux);

        double location = ((double)current_video_duration / (double)total_video_duration_1) * 100;
        pthread_mutex_lock(&mux);
        lv_slider_set_value(slider, (int)location, LV_ANIM_OFF);
        pthread_mutex_unlock(&mux);

        sleep(1);
    }
}

//视频播放界面
void video_menu()
{
    video_playback_interface();

    // 3.创建播放视频的线程
    pthread_t thread_id_play;
    if(pthread_create(&thread_id_play, NULL, play, NULL) != 0) {
        perror("pthread_create");
        return;
    }

    usleep(1000);

    //更新数据
    pthread_t thread_id_text;
    if(pthread_create(&thread_id_text, NULL, update_the_current_video_time, NULL) != 0) {
        perror("pthread_create");
        return;
    }
}

1.5.5控制音乐播放的各类控件

//创建mp3进度条
lv_obj_t * create_mp3_progress_bar(int total_music_duration)
{
    int m = 0;
    int s = 0;

    /* 4. 创建一个进度条 */
    mp3_slider = lv_slider_create(lv_scr_act());           // 创建一个进度条,并添加到当前活动的屏幕
    lv_obj_set_size(mp3_slider, 700, 10);                  // 设置进度条的宽度和高度
    lv_obj_align(mp3_slider, LV_ALIGN_BOTTOM_MID, 0, -90); // 将按钮居中放置

    /* 5. 设置进度条的值范围 */
    lv_slider_set_range(mp3_slider, 0, 100); // 设置最小值为0,最大值为100

    //创建两个标签表示当前视频时间 和 总视频时间
    //创建表示当前视频时间标签
    mp3_label_pos = lv_label_create(lv_scr_act());
    lv_obj_set_style_text_font(mp3_label_pos, &lv_font_montserrat_16, 0); // 设置标签文本
    lv_label_set_text(mp3_label_pos, "00:00");
    lv_obj_align_to(mp3_label_pos, mp3_slider, LV_ALIGN_OUT_BOTTOM_LEFT, 5, 5); // 将标签居中放置在按钮上

    //创建表示总视频时间标签
    mp3_label_total = lv_label_create(lv_scr_act());
    lv_obj_set_style_text_font(mp3_label_total, &lv_font_montserrat_16, 0); // 设置标签文本
    m             = total_music_duration / 60;
    s             = total_music_duration % 60;
    char temp[50] = {0};
    if(s <= 9) {
        sprintf(temp, "0%d:0%d", m, s);
    } else {
        sprintf(temp, "0%d:%d", m, s);
    }
    lv_label_set_text(mp3_label_total, temp);
    lv_obj_align_to(mp3_label_total, mp3_slider, LV_ALIGN_OUT_BOTTOM_RIGHT, -5, 5); // 将标签居中放置在按钮上

    return NULL;
}

//创建歌词标签
void lyrics_tags()
{
    // 创建标签
    lyrics_label = lv_label_create(lv_scr_act());

    // 设置标签的文本内容
    lv_label_set_text(lyrics_label, "我落泪 情绪零碎");

    // 设置标签的字体
    lv_obj_set_style_text_font(lyrics_label, &font_gc_20, 0);

    // 设置标签的对齐方式
    lv_obj_align(lyrics_label, LV_ALIGN_CENTER, 0, 50);
}

//清除按钮控件
void clear_button_control()
{
    lv_obj_del(btn_stopmusic); // 删除按钮
    lv_obj_del(btn_nextmusic); // 删除按钮
    lv_obj_del(btn_fearmusic); // 删除按钮
    lv_obj_del(btn_cancle_music); // 删除按钮

    lv_obj_del(mp3_slider); // 删除进度条
    lv_obj_del(mp3_label_pos); // 删除标签
    lv_obj_del(mp3_label_total); // 删除标签
    
}

//创建基本音乐控件
void create_music_control()
{
    //创建背景图
    // backgrand.bmp
    display_background_image("A:/backgrand2.bmp");

    // 暂停播放
    btn_stopmusic = create_button_with_image(lv_scr_act(), 0, -10, "A:/kj_pic/stop.bmp");
    lv_obj_add_event_cb(btn_stopmusic, my_event_stopmusic, LV_EVENT_CLICKED, NULL);

    // 下一首
    btn_nextmusic = create_button_with_image(lv_scr_act(), 170, -10, "A:/kj_pic/next.bmp");
    lv_obj_add_event_cb(btn_nextmusic, my_event_nextmusic, LV_EVENT_CLICKED, 4);

    // 上一首
    btn_fearmusic = create_button_with_image(lv_scr_act(), -180, -10, "A:/kj_pic/fear.bmp");
    lv_obj_add_event_cb(btn_fearmusic, my_event_fearmusic, LV_EVENT_CLICKED, 4);

    //创建一个进度条
    create_mp3_progress_bar(total_music_duration);

    //显示专辑图片
    display_album_images();

    //创建一个歌词标签
    lyrics_tags();

    //创建一个返回按钮
    btn_cancle_music = create_button_with_image(lv_scr_act(), -350, -400, "A:/kj_pic/cancle2.bmp");
    lv_obj_add_event_cb(btn_cancle_music, my_event_cancle_music, LV_EVENT_CLICKED, 4);
}

//显示专辑图片
void display_album_images()
{
    /* 创建一个图片对象在当前屏幕上 */
    album_img_obj = lv_img_create(lv_scr_act());

    /* 设置图片源为文件路径 */
    lv_img_set_src(album_img_obj, "A:/my_music/woluolei.bmp");

    /* 调整图片对象的位置和大小(如果需要) */
    lv_obj_align(album_img_obj, LV_ALIGN_CENTER, 0, -100); // 设置图片对象的位置
    lv_obj_set_size(album_img_obj, 200, 200);              // 设置图片对象的大小
}

//显示背景图片
void display_background_image(char * path)
{
    /* 创建一个图片对象在当前屏幕上 */
    background_obj = lv_img_create(lv_scr_act());

    /* 设置图片源为文件路径 */
    lv_img_set_src(background_obj, path);

    /* 调整图片对象的位置和大小(如果需要) */
    lv_obj_align(background_obj, LV_ALIGN_CENTER, 0, 0); // 设置图片对象的位置
    lv_obj_set_size(background_obj, 800, 480);           // 设置图片对象的大小
}
//更新歌词
void print_lyrics(char * time, char * file_name)
{
    //初始化锁
    pthread_mutex_init(&mux, NULL);

    // 打开歌词文件
    FILE * file = fopen(file_name, "r");
    if(!file) {
        perror("Error opening file");
        return;
    }

    // 定义字符串变量
    char line[256];     // 存储每行歌词
    char timestamp[10]; // 存储时间戳
    char lyric[100];    // 存储歌词文本

    printf("---------%s\n", time);

    // 逐行读取歌词文件
    while(fgets(line, sizeof(line), file)) {
        // 从原始字符串中截取时间戳的整数部分
        strncpy(timestamp, line + 1, 5); // 跳过开头的 '[',截取 5 个字符
        timestamp[5] = '\0';             // 添加字符串结束符
        // 检查时间戳是否匹配
        if(strncmp(timestamp, time, strlen(time)) == 0) {
            // 提取歌词文本
            char * space_pos = strchr(line, ']');
            // printf("%s\n", space_pos);
            if(space_pos) {
                strcpy(lyric, space_pos + 1); // 从空格位置开始截取剩余字符串

                //将字符串写入标签中
                pthread_mutex_lock(&mux);
                lv_label_set_text(lyrics_label, lyric);
                pthread_mutex_unlock(&mux);

                break; // 找到匹配的时间戳后退出循环
            }
        }
    }

    // 关闭歌词文件
    fclose(file);
}

//更新当前视频时间
void * update_the_current_music_time(void * arg)
{
    //初始化锁
    pthread_mutex_init(&mux, NULL);

    while(!stop_thread_music) {
        int m = 0;
        int s = 0;

        m = current_music_duration / 60;
        s = current_music_duration % 60;

        char temp[50] = {0};
        if(s <= 9) {
            sprintf(temp, "0%d:0%d", m, s);
        } else {
            sprintf(temp, "0%d:%d", m, s);
        }

        //更新标签
        pthread_mutex_lock(&mux);
        lv_label_set_text(mp3_label_pos, temp);
        pthread_mutex_unlock(&mux);

        //更新进度条
        double location = ((double)current_music_duration / (double)total_music_duration) * 100;
        pthread_mutex_lock(&mux);
        lv_slider_set_value(mp3_slider, (int)location, LV_ANIM_OFF);
        pthread_mutex_unlock(&mux);

        // usleep(50000);

        sleep(1);

        //更新歌词
        print_lyrics(temp, file_name);

        // usleep(20000);
    }

    return NULL;


}

// 控制音乐播放(包含 控件 和 进度条)
void music_playback_interface()
{
    //创建一个通信管道
    mkfifo("/pipe", 0777);

    //创建音乐播放控件
    create_music_control();
}

//音乐播放界面
void music_menu()
{
    music_playback_interface();

    // 3.创建播放音乐的线程

    if(pthread_create(&thread_id_music, NULL, music, NULL) != 0) {
        perror("pthread_create");
        return;
    }

    usleep(1000);

    //更新数据
    if(pthread_create(&thread_id_music_text, NULL, update_the_current_music_time, NULL) != 0) {
        perror("pthread_create");
        return;
    }
}

1.5.6控制主界面的控件

/-----主界面-------

void my_event_play_menu(lv_event_t * event)
{
    //清除控件
    clear_button_control();

    video_menu();
}

void my_event_music_menu(lv_event_t * event)
{
    music_menu();
}

//显示桌面
void display_desktop()
{
    //显示背景图
    display_background_image("A:/backgrand.bmp");

    //显示两图片按钮
    lv_obj_t * btn_play_menu = create_button_with_image(lv_scr_act(), 100, -200, "A:/kj_pic/video.bmp");
    lv_obj_add_event_cb(btn_play_menu, my_event_play_menu, LV_EVENT_CLICKED, NULL);

    lv_obj_t * btn_music_menu = create_button_with_image(lv_scr_act(), -100, -200, "A:/kj_pic/music.bmp");
    lv_obj_add_event_cb(btn_music_menu, my_event_music_menu, LV_EVENT_CLICKED, NULL);
}

1.6技术难点总结

  1.  在创建主界面时,我通过创建两个图片按钮,添加点击事件,即当点击按钮时,触发点击事件,能够运行对应的功能函数
  2. 在创建播放器界面时,首先通过popen打开mplayer进程,并用一个线程不断获取当前音乐播放进度,实时更新时间标签和歌词显示。音乐播放器基本控件界面与主界面设计大致相同。
  3. 实现控件的触发事件,主要是向mplay进程发送一系列的命令,例如当想mplayer暂停,就发送“Killall -Stop mplayer”,希望继续播放就发送“Killall -CONT  mplayer”.等等。
  4. 在实现功能模块分离时,要注意线程安全,防止线程间阻塞导致的死锁(可通过互斥锁对线程间的控制)

1.7项目代码开源

        见我博客简介ヾ(◍°∇°◍)ノ゙

                                                     

标签:影音,obj,create,lv,A53,void,Cortex,include,event
From: https://blog.csdn.net/weixin_72119871/article/details/143201978

相关文章

  • Cortex-M3及以上32单片机使用内核DWT实现微秒级延时
    目录一、什么是DWT二、为什么要使用DWT实现延时2.1延时方法2.2上述两种方案的缺点三、如何实现DWT延时 3.1DEMCR寄存器3.2DWT_CTRL寄存器与DWT_CYCCNT寄存器四、代码实现五、验证延时函数一、什么是DWT        在Cortex-M3及以上的内核中有一个外设......
  • ARM Cortex-M3/M4内核架构:中断处理过程
    目录一、概述1.保存现场?什么是现场?现场包括什么?2.怎么处理异常?我们先来简单介绍下。3.又怎么恢复现场?4.异常进入流程(核心流程)二、保存现场三、恢复现场1、EXC_RETURN2、恢复现场四、异常处理优化1、末尾连锁2、延时到达3、出栈抢占五、总结一、概述中断......
  • Cortex-M3/M4/M7 芯片 Fault 分析原理与实战
    目录一、简介1、异常类型2、异常优先级3、同步异步问题4、异常具体类型二、Faultexceptionregisters1、Controlregisters1.1CCR1.2SHP1.3SHCSR2、Statusandaddressregisters2.1HardFaultStatusRegister——HSFR2.2ConfigurableFaultStatusRegister——......
  • Singularity 2 - 400个大气史诗电影预告片/轰隆声/风声/上升/张力/呼啸声/嗡嗡声/暗淡
    SINGULARITY2–CINEMATICSOUNDEFFECTSLIBRARY广受赞誉的电影音效库SINGULARITY的后续更新作品。电影人必须拥有的音效库。Singularity2包括400个原始声音,旨在帮助您创建惊人的电影电影。特性–400个原创音效–专业的掌握–全部为WAV格式(1.2GB)–兼容任......
  • PY32 link仿真器,支持PY32系列ARM-Cortex内核单片机的调试烧录
    PY32系列32位单片机基于Arm®Cortex®-M处理器,包括M0+和M4系列产品。集高性能、实时操作、数字信号处理、低功耗性能、高性价比等特性于一身,同时还保持了系统简单、易于开发的特点,符合消费市场的基本设计需求,受到广大开发者的喜爱。PY32系列单片机适用于消费类、工业类,数字控制等......
  • Arch搭建Nas系统(7)之七:影音服务
    1.7.1安装jellyfin准备驱动目录和字体文件mkdir-p/nas/jellyfin/configmkdir-p/nas/jellyfin/cache#查看是否有硬解驱动ls/dev/dri/#下载中文思源字体mkdir-p/nas/jellyfin/config/fontscd/nas/jellyfin/config/fontswget-OSource_Han_Sans_CN_Regular.......
  • Cortex-A7 MPCore 架构
    Cortex-A7MPCore架构 1)Cortex-A7MPCore简介Cortex-A7MPcore处理器支持1~4核,通常是和Cortex-A15组成big.LITTLE架构的,Cortex-A15作为大核负责高性能运算,比如玩游戏啥的,Cortex-A7负责普通应用,因为CortexA7省电。Cortex-A7本身性能也不弱,不要看它叫做Cortex-......
  • Hi3559A/C V100 集成了双核 A73 和双核 A53,支持 8K30/4K120 视频录制
    1.1概述Hi3559AV100是专业的8KUltraHDMobileCameraSOC,它提供了8K30/4K120广播级图像质量的数字视频录制,支持多路Sensor输入,支持H.265编码输出或影视级的RAW数据输出,并集成高性能ISP处理,同时采用先进低功耗工艺和低功耗架构设计......
  • Cortex-A7的GIC(通用中断控制器):边沿触发和电平触发中断的区别
    0资料ARM®GenericInterruptControllerArchitectureversion2.0ArchitectureSpecification1边沿触发和电平触发中断的区别1.1边沿触发和电平触发中断官方解释边沿触发(Edge-triggered)Thisisaninterruptthatisassertedondetectionofarisingedge......
  • Cortex-A7的GIC(通用中断控制器):边沿触发和电平触发中断处理流程
    0资料ARM®GenericInterruptControllerArchitectureversion2.0ArchitectureSpecification1边沿触发和电平触发中断处理流程1.0边沿触发和电平触发的区别边沿触发(Edge-triggered)Thisisaninterruptthatisassertedondetectionofarisingedgeofa......